diff --git a/.gitignore b/.gitignore
index eb8378e..f9809d6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
-SOURCES/krb5-1.16.1-pdfs.tar
-SOURCES/krb5-1.16.1.tar.gz
+SOURCES/krb5-1.17-pdfs.tar
+SOURCES/krb5-1.17.tar.gz
diff --git a/.krb5.metadata b/.krb5.metadata
index d788450..5858b94 100644
--- a/.krb5.metadata
+++ b/.krb5.metadata
@@ -1,2 +1,2 @@
-494c62bea08e5d26e01d47c409ac745b65e509c8 SOURCES/krb5-1.16.1-pdfs.tar
-8353f2d900a7d52499c7c2605d5e295f71dd5e67 SOURCES/krb5-1.16.1.tar.gz
+494c62bea08e5d26e01d47c409ac745b65e509c8 SOURCES/krb5-1.17-pdfs.tar
+0c404b081db9c996c581f636ce450ee28778f338 SOURCES/krb5-1.17.tar.gz
diff --git a/SOURCES/Add-ASN.1-encoders-and-decoders-for-SPAKE-types.patch b/SOURCES/Add-ASN.1-encoders-and-decoders-for-SPAKE-types.patch
deleted file mode 100644
index 6e78dcc..0000000
--- a/SOURCES/Add-ASN.1-encoders-and-decoders-for-SPAKE-types.patch
+++ /dev/null
@@ -1,866 +0,0 @@
-From dff5177801444307d19071fc4fac7de864fda92a Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Sat, 13 Jun 2015 16:04:53 -0400
-Subject: [PATCH] Add ASN.1 encoders and decoders for SPAKE types
-
-Add a new internal header k5-spake.h.  Add ASN.1 encoder and decoder
-functions and an internal free function for SPAKE types.  Add ASN.1
-tests and asn1c test vectors the new types.
-
-The additions to to make-vectors.c use C99 designated initializers in
-order to initialize unions.  This is okay since make-vectors.c is only
-compiled as part of "make test-vectors" and not as part of the regular
-build.
-
-(cherry picked from commit 78a09d95dff6915da4079bc611f4bb95f6a95f70)
----
- src/include/k5-spake.h               | 107 +++++++++++++++++++++++++++
- src/lib/krb5/asn.1/asn1_k_encode.c   |  52 ++++++++++++-
- src/lib/krb5/krb/kfree.c             |  40 ++++++++++
- src/lib/krb5/libkrb5.exports         |   6 ++
- src/tests/asn.1/Makefile.in          |   2 +-
- src/tests/asn.1/krb5_decode_test.c   |  37 +++++++++
- src/tests/asn.1/krb5_encode_test.c   |  29 ++++++++
- src/tests/asn.1/ktest.c              |  97 ++++++++++++++++++++++++
- src/tests/asn.1/ktest.h              |   9 +++
- src/tests/asn.1/ktest_equal.c        |  49 ++++++++++++
- src/tests/asn.1/ktest_equal.h        |   6 ++
- src/tests/asn.1/make-vectors.c       |  56 ++++++++++++++
- src/tests/asn.1/reference_encode.out |   6 ++
- src/tests/asn.1/spake.asn1           |  44 +++++++++++
- src/tests/asn.1/trval_reference.out  |  50 +++++++++++++
- 15 files changed, 588 insertions(+), 2 deletions(-)
- create mode 100644 src/include/k5-spake.h
- create mode 100644 src/tests/asn.1/spake.asn1
-
-diff --git a/src/include/k5-spake.h b/src/include/k5-spake.h
-new file mode 100644
-index 000000000..ddb5d810d
---- /dev/null
-+++ b/src/include/k5-spake.h
-@@ -0,0 +1,107 @@
-+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-+/* include/k5-spake.h - SPAKE preauth mech declarations */
-+/*
-+ * Copyright (C) 2015 by the Massachusetts Institute of Technology.
-+ * 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.
-+ *
-+ * 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 HOLDER 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.
-+ */
-+
-+/*
-+ * The SPAKE preauth mechanism allows long-term client keys to be used for
-+ * preauthentication without exposing them to offline dictionary attacks.  The
-+ * negotiated key can also be used for second-factor authentication.  This
-+ * header file declares structures and encoder/decoder functions for the
-+ * mechanism's padata messages.
-+ */
-+
-+#ifndef K5_SPAKE_H
-+#define K5_SPAKE_H
-+
-+#include "k5-int.h"
-+
-+/* SPAKESecondFactor is contained within a SPAKEChallenge, SPAKEResponse, or
-+ * EncryptedData message and contains a second-factor challenge or response. */
-+typedef struct krb5_spake_factor_st {
-+    int32_t type;
-+    krb5_data *data;
-+} krb5_spake_factor;
-+
-+/* SPAKESupport is sent from the client to the KDC to indicate which group the
-+ * client supports. */
-+typedef struct krb5_spake_support_st {
-+    int32_t ngroups;
-+    int32_t *groups;
-+} krb5_spake_support;
-+
-+/* SPAKEChallenge is sent from the KDC to the client to communicate its group
-+ * selection, public value, and second-factor challenge options. */
-+typedef struct krb5_spake_challenge_st {
-+    int32_t group;
-+    krb5_data pubkey;
-+    krb5_spake_factor **factors;
-+} krb5_spake_challenge;
-+
-+/* SPAKEResponse is sent from the client to the KDC to communicate its public
-+ * value and encrypted second-factor response. */
-+typedef struct krb5_spake_response_st {
-+    krb5_data pubkey;
-+    krb5_enc_data factor;
-+} krb5_spake_response;
-+
-+enum krb5_spake_msgtype {
-+    SPAKE_MSGTYPE_UNKNOWN = -1,
-+    SPAKE_MSGTYPE_SUPPORT = 0,
-+    SPAKE_MSGTYPE_CHALLENGE = 1,
-+    SPAKE_MSGTYPE_RESPONSE = 2,
-+    SPAKE_MSGTYPE_ENCDATA = 3
-+};
-+
-+/* PA-SPAKE is a choice among the message types which can appear in a PA-SPAKE
-+ * padata element. */
-+typedef struct krb5_pa_spake_st {
-+    enum krb5_spake_msgtype choice;
-+    union krb5_spake_message_choices {
-+        krb5_spake_support support;
-+        krb5_spake_challenge challenge;
-+        krb5_spake_response response;
-+        krb5_enc_data encdata;
-+    } u;
-+} krb5_pa_spake;
-+
-+krb5_error_code encode_krb5_spake_factor(const krb5_spake_factor *val,
-+                                         krb5_data **code_out);
-+krb5_error_code decode_krb5_spake_factor(const krb5_data *code,
-+                                         krb5_spake_factor **val_out);
-+void k5_free_spake_factor(krb5_context context, krb5_spake_factor *val);
-+
-+krb5_error_code encode_krb5_pa_spake(const krb5_pa_spake *val,
-+                                     krb5_data **code_out);
-+krb5_error_code decode_krb5_pa_spake(const krb5_data *code,
-+                                     krb5_pa_spake **val_out);
-+void k5_free_pa_spake(krb5_context context, krb5_pa_spake *val);
-+
-+#endif /* K5_SPAKE_H */
-diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c
-index 3b23fe34a..29f6b903d 100644
---- a/src/lib/krb5/asn.1/asn1_k_encode.c
-+++ b/src/lib/krb5/asn.1/asn1_k_encode.c
-@@ -25,7 +25,7 @@
-  */
- 
- #include "asn1_encode.h"
--#include <assert.h>
-+#include "k5-spake.h"
- 
- DEFINT_IMMEDIATE(krb5_version, KVNO, KRB5KDC_ERR_BAD_PVNO);
- 
-@@ -1817,3 +1817,53 @@ static const struct atype_info *secure_cookie_fields[] = {
- DEFSEQTYPE(secure_cookie, krb5_secure_cookie, secure_cookie_fields);
- MAKE_ENCODER(encode_krb5_secure_cookie, secure_cookie);
- MAKE_DECODER(decode_krb5_secure_cookie, secure_cookie);
-+
-+DEFFIELD(spake_factor_0, krb5_spake_factor, type, 0, int32);
-+DEFFIELD(spake_factor_1, krb5_spake_factor, data, 1, opt_ostring_data_ptr);
-+static const struct atype_info *spake_factor_fields[] = {
-+    &k5_atype_spake_factor_0, &k5_atype_spake_factor_1
-+};
-+DEFSEQTYPE(spake_factor, krb5_spake_factor, spake_factor_fields);
-+DEFPTRTYPE(spake_factor_ptr, spake_factor);
-+DEFNULLTERMSEQOFTYPE(seqof_spake_factor, spake_factor_ptr);
-+DEFPTRTYPE(ptr_seqof_spake_factor, seqof_spake_factor);
-+MAKE_ENCODER(encode_krb5_spake_factor, spake_factor);
-+MAKE_DECODER(decode_krb5_spake_factor, spake_factor);
-+
-+DEFCNFIELD(spake_support_0, krb5_spake_support, groups, ngroups, 0,
-+           cseqof_int32);
-+static const struct atype_info *spake_support_fields[] = {
-+    &k5_atype_spake_support_0
-+};
-+DEFSEQTYPE(spake_support, krb5_spake_support, spake_support_fields);
-+
-+DEFFIELD(spake_challenge_0, krb5_spake_challenge, group, 0, int32);
-+DEFFIELD(spake_challenge_1, krb5_spake_challenge, pubkey, 1, ostring_data);
-+DEFFIELD(spake_challenge_2, krb5_spake_challenge, factors, 2,
-+         ptr_seqof_spake_factor);
-+static const struct atype_info *spake_challenge_fields[] = {
-+    &k5_atype_spake_challenge_0, &k5_atype_spake_challenge_1,
-+    &k5_atype_spake_challenge_2
-+};
-+DEFSEQTYPE(spake_challenge, krb5_spake_challenge, spake_challenge_fields);
-+
-+DEFFIELD(spake_response_0, krb5_spake_response, pubkey, 0, ostring_data);
-+DEFFIELD(spake_response_1, krb5_spake_response, factor, 1, encrypted_data);
-+static const struct atype_info *spake_response_fields[] = {
-+    &k5_atype_spake_response_0, &k5_atype_spake_response_1,
-+};
-+DEFSEQTYPE(spake_response, krb5_spake_response, spake_response_fields);
-+
-+DEFCTAGGEDTYPE(pa_spake_0, 0, spake_support);
-+DEFCTAGGEDTYPE(pa_spake_1, 1, spake_challenge);
-+DEFCTAGGEDTYPE(pa_spake_2, 2, spake_response);
-+DEFCTAGGEDTYPE(pa_spake_3, 3, encrypted_data);
-+static const struct atype_info *pa_spake_alternatives[] = {
-+    &k5_atype_pa_spake_0, &k5_atype_pa_spake_1, &k5_atype_pa_spake_2,
-+    &k5_atype_pa_spake_3
-+};
-+DEFCHOICETYPE(pa_spake_choice, union krb5_spake_message_choices,
-+              enum krb5_spake_msgtype, pa_spake_alternatives);
-+DEFCOUNTEDTYPE_SIGNED(pa_spake, krb5_pa_spake, u, choice, pa_spake_choice);
-+MAKE_ENCODER(encode_krb5_pa_spake, pa_spake);
-+MAKE_DECODER(decode_krb5_pa_spake, pa_spake);
-diff --git a/src/lib/krb5/krb/kfree.c b/src/lib/krb5/krb/kfree.c
-index a631807d3..e1ea1494a 100644
---- a/src/lib/krb5/krb/kfree.c
-+++ b/src/lib/krb5/krb/kfree.c
-@@ -51,6 +51,7 @@
-  */
- 
- #include "k5-int.h"
-+#include "k5-spake.h"
- #include <assert.h>
- 
- void KRB5_CALLCONV
-@@ -890,3 +891,42 @@ k5_free_secure_cookie(krb5_context context, krb5_secure_cookie *val)
-     k5_zapfree_pa_data(val->data);
-     free(val);
- }
-+
-+void
-+k5_free_spake_factor(krb5_context context, krb5_spake_factor *val)
-+{
-+    if (val == NULL)
-+        return;
-+    krb5_free_data(context, val->data);
-+    free(val);
-+}
-+
-+void
-+k5_free_pa_spake(krb5_context context, krb5_pa_spake *val)
-+{
-+    krb5_spake_factor **f;
-+
-+    if (val == NULL)
-+        return;
-+    switch (val->choice) {
-+    case SPAKE_MSGTYPE_SUPPORT:
-+        free(val->u.support.groups);
-+        break;
-+    case SPAKE_MSGTYPE_CHALLENGE:
-+        krb5_free_data_contents(context, &val->u.challenge.pubkey);
-+        for (f = val->u.challenge.factors; f != NULL && *f != NULL; f++)
-+            k5_free_spake_factor(context, *f);
-+        free(val->u.challenge.factors);
-+        break;
-+    case SPAKE_MSGTYPE_RESPONSE:
-+        krb5_free_data_contents(context, &val->u.response.pubkey);
-+        krb5_free_data_contents(context, &val->u.response.factor.ciphertext);
-+        break;
-+    case SPAKE_MSGTYPE_ENCDATA:
-+        krb5_free_data_contents(context, &val->u.encdata.ciphertext);
-+        break;
-+    default:
-+        break;
-+    }
-+    free(val);
-+}
-diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
-index ed6cad6ad..622bc3673 100644
---- a/src/lib/krb5/libkrb5.exports
-+++ b/src/lib/krb5/libkrb5.exports
-@@ -36,6 +36,7 @@ decode_krb5_pa_otp_req
- decode_krb5_pa_otp_enc_req
- decode_krb5_pa_pac_req
- decode_krb5_pa_s4u_x509_user
-+decode_krb5_pa_spake
- decode_krb5_padata_sequence
- decode_krb5_priv
- decode_krb5_safe
-@@ -44,6 +45,7 @@ decode_krb5_sam_challenge_2_body
- decode_krb5_sam_response_2
- decode_krb5_secure_cookie
- decode_krb5_setpw_req
-+decode_krb5_spake_factor
- decode_krb5_tgs_rep
- decode_krb5_tgs_req
- decode_krb5_ticket
-@@ -85,6 +87,7 @@ encode_krb5_pa_otp_challenge
- encode_krb5_pa_otp_req
- encode_krb5_pa_otp_enc_req
- encode_krb5_pa_s4u_x509_user
-+encode_krb5_pa_spake
- encode_krb5_padata_sequence
- encode_krb5_pkinit_supp_pub_info
- encode_krb5_priv
-@@ -95,6 +98,7 @@ encode_krb5_sam_challenge_2_body
- encode_krb5_sam_response_2
- encode_krb5_secure_cookie
- encode_krb5_sp80056a_other_info
-+encode_krb5_spake_factor
- encode_krb5_tgs_rep
- encode_krb5_tgs_req
- encode_krb5_ticket
-@@ -128,7 +132,9 @@ k5_free_kkdcp_message
- k5_free_pa_otp_challenge
- k5_free_pa_otp_req
- k5_free_secure_cookie
-+k5_free_pa_spake
- k5_free_serverlist
-+k5_free_spake_factor
- k5_hostrealm_free_context
- k5_init_trace
- k5_is_string_numeric
-diff --git a/src/tests/asn.1/Makefile.in b/src/tests/asn.1/Makefile.in
-index fec4e109e..ec9c67495 100644
---- a/src/tests/asn.1/Makefile.in
-+++ b/src/tests/asn.1/Makefile.in
-@@ -9,7 +9,7 @@ SRCS= $(srcdir)/krb5_encode_test.c $(srcdir)/krb5_decode_test.c \
- 
- ASN1SRCS= $(srcdir)/krb5.asn1 $(srcdir)/pkix.asn1 $(srcdir)/otp.asn1 \
- 	$(srcdir)/pkinit.asn1 $(srcdir)/pkinit-agility.asn1 \
--	$(srcdir)/cammac.asn1
-+	$(srcdir)/cammac.asn1 $(srcdir)/spake.asn1
- 
- all: krb5_encode_test krb5_decode_test krb5_decode_leak t_trval
- 
-diff --git a/src/tests/asn.1/krb5_decode_test.c b/src/tests/asn.1/krb5_decode_test.c
-index f17f9b1f1..ee70fa4b9 100644
---- a/src/tests/asn.1/krb5_decode_test.c
-+++ b/src/tests/asn.1/krb5_decode_test.c
-@@ -25,6 +25,7 @@
-  */
- 
- #include "k5-int.h"
-+#include "k5-spake.h"
- #include "ktest.h"
- #include "com_err.h"
- #include "utility.h"
-@@ -1107,6 +1108,42 @@ int main(argc, argv)
-         ktest_empty_secure_cookie(&ref);
-     }
- 
-+    /****************************************************************/
-+    /* decode_krb5_spake_factor */
-+    {
-+        setup(krb5_spake_factor,ktest_make_minimal_spake_factor);
-+        decode_run("spake_factor","(optionals NULL)","30 05 A0 03 02 01 01",decode_krb5_spake_factor,ktest_equal_spake_factor,k5_free_spake_factor);
-+        ktest_empty_spake_factor(&ref);
-+    }
-+    {
-+        setup(krb5_spake_factor,ktest_make_maximal_spake_factor);
-+        decode_run("spake_factor","","30 0E A0 03 02 01 02 A1 07 04 05 66 64 61 74 61",decode_krb5_spake_factor,ktest_equal_spake_factor,k5_free_spake_factor);
-+        ktest_empty_spake_factor(&ref);
-+    }
-+
-+    /****************************************************************/
-+    /* decode_krb5_pa_spake */
-+    {
-+        setup(krb5_pa_spake,ktest_make_support_pa_spake);
-+        decode_run("pa_spake","(support)","A0 0C 30 0A A0 08 30 06 02 01 01 02 01 02",decode_krb5_pa_spake,ktest_equal_pa_spake,k5_free_pa_spake);
-+        ktest_empty_pa_spake(&ref);
-+    }
-+    {
-+        setup(krb5_pa_spake,ktest_make_challenge_pa_spake);
-+        decode_run("pa_spake","(challenge)","A1 2D 30 2B A0 03 02 01 01 A1 09 04 07 54 20 76 61 6C 75 65 A2 19 30 17 30 05 A0 03 02 01 01 30 0E A0 03 02 01 02 A1 07 04 05 66 64 61 74 61",decode_krb5_pa_spake,ktest_equal_pa_spake,k5_free_pa_spake);
-+        ktest_empty_pa_spake(&ref);
-+    }
-+    {
-+        setup(krb5_pa_spake,ktest_make_response_pa_spake);
-+        decode_run("pa_spake","(response)","A2 34 30 32 A0 09 04 07 53 20 76 61 6C 75 65 A1 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_pa_spake,ktest_equal_pa_spake,k5_free_pa_spake);
-+        ktest_empty_pa_spake(&ref);
-+    }
-+    {
-+        setup(krb5_pa_spake,ktest_make_encdata_pa_spake);
-+        decode_run("pa_spake","(encdata)","A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_pa_spake,ktest_equal_pa_spake,k5_free_pa_spake);
-+        ktest_empty_pa_spake(&ref);
-+    }
-+
- #ifndef DISABLE_PKINIT
- 
-     /****************************************************************/
-diff --git a/src/tests/asn.1/krb5_encode_test.c b/src/tests/asn.1/krb5_encode_test.c
-index f5710b68c..3efbfb4c0 100644
---- a/src/tests/asn.1/krb5_encode_test.c
-+++ b/src/tests/asn.1/krb5_encode_test.c
-@@ -759,6 +759,35 @@ main(argc, argv)
-         encode_run(cookie, "secure_cookie", "", encode_krb5_secure_cookie);
-         ktest_empty_secure_cookie(&cookie);
-     }
-+    /****************************************************************/
-+    /* encode_krb5_spake_factor */
-+    {
-+        krb5_spake_factor factor;
-+        ktest_make_minimal_spake_factor(&factor);
-+        encode_run(factor, "spake_factor", "(optionals NULL)",
-+                   encode_krb5_spake_factor);
-+        ktest_empty_spake_factor(&factor);
-+        ktest_make_maximal_spake_factor(&factor);
-+        encode_run(factor, "spake_factor", "", encode_krb5_spake_factor);
-+        ktest_empty_spake_factor(&factor);
-+    }
-+    /****************************************************************/
-+    /* encode_krb5_pa_spake */
-+    {
-+        krb5_pa_spake pa_spake;
-+        ktest_make_support_pa_spake(&pa_spake);
-+        encode_run(pa_spake, "pa_spake", "(support)", encode_krb5_pa_spake);
-+        ktest_empty_pa_spake(&pa_spake);
-+        ktest_make_challenge_pa_spake(&pa_spake);
-+        encode_run(pa_spake, "pa_spake", "(challenge)", encode_krb5_pa_spake);
-+        ktest_empty_pa_spake(&pa_spake);
-+        ktest_make_response_pa_spake(&pa_spake);
-+        encode_run(pa_spake, "pa_spake", "(response)", encode_krb5_pa_spake);
-+        ktest_empty_pa_spake(&pa_spake);
-+        ktest_make_encdata_pa_spake(&pa_spake);
-+        encode_run(pa_spake, "pa_spake", "(encdata)", encode_krb5_pa_spake);
-+        ktest_empty_pa_spake(&pa_spake);
-+    }
- #ifndef DISABLE_PKINIT
-     /****************************************************************/
-     /* encode_krb5_pa_pk_as_req */
-diff --git a/src/tests/asn.1/ktest.c b/src/tests/asn.1/ktest.c
-index cf63f3f66..5bfdc5be2 100644
---- a/src/tests/asn.1/ktest.c
-+++ b/src/tests/asn.1/ktest.c
-@@ -1018,6 +1018,66 @@ ktest_make_sample_secure_cookie(krb5_secure_cookie *p)
-     p->time = SAMPLE_TIME;
- }
- 
-+void
-+ktest_make_minimal_spake_factor(krb5_spake_factor *p)
-+{
-+    p->type = 1;
-+    p->data = NULL;
-+}
-+
-+void
-+ktest_make_maximal_spake_factor(krb5_spake_factor *p)
-+{
-+    p->type = 2;
-+    p->data = ealloc(sizeof(*p->data));
-+    krb5_data_parse(p->data, "fdata");
-+}
-+
-+void
-+ktest_make_support_pa_spake(krb5_pa_spake *p)
-+{
-+    krb5_spake_support *s = &p->u.support;
-+
-+    s->ngroups = 2;
-+    s->groups = ealloc(s->ngroups * sizeof(*s->groups));
-+    s->groups[0] = 1;
-+    s->groups[1] = 2;
-+    p->choice = SPAKE_MSGTYPE_SUPPORT;
-+}
-+
-+void
-+ktest_make_challenge_pa_spake(krb5_pa_spake *p)
-+{
-+    krb5_spake_challenge *c = &p->u.challenge;
-+
-+    c->group = 1;
-+    krb5_data_parse(&c->pubkey, "T value");
-+    c->factors = ealloc(3 * sizeof(*c->factors));
-+    c->factors[0] = ealloc(sizeof(*c->factors[0]));
-+    ktest_make_minimal_spake_factor(c->factors[0]);
-+    c->factors[1] = ealloc(sizeof(*c->factors[1]));
-+    ktest_make_maximal_spake_factor(c->factors[1]);
-+    c->factors[2] = NULL;
-+    p->choice = SPAKE_MSGTYPE_CHALLENGE;
-+}
-+
-+void
-+ktest_make_response_pa_spake(krb5_pa_spake *p)
-+{
-+    krb5_spake_response *r = &p->u.response;
-+
-+    krb5_data_parse(&r->pubkey, "S value");
-+    ktest_make_sample_enc_data(&r->factor);
-+    p->choice = SPAKE_MSGTYPE_RESPONSE;
-+}
-+
-+void
-+ktest_make_encdata_pa_spake(krb5_pa_spake *p)
-+{
-+    ktest_make_sample_enc_data(&p->u.encdata);
-+    p->choice = SPAKE_MSGTYPE_ENCDATA;
-+}
-+
- /****************************************************************/
- /* destructors */
- 
-@@ -1858,3 +1918,40 @@ ktest_empty_secure_cookie(krb5_secure_cookie *p)
- {
-     ktest_empty_pa_data_array(p->data);
- }
-+
-+void
-+ktest_empty_spake_factor(krb5_spake_factor *p)
-+{
-+    krb5_free_data(NULL, p->data);
-+    p->data = NULL;
-+}
-+
-+void
-+ktest_empty_pa_spake(krb5_pa_spake *p)
-+{
-+    krb5_spake_factor **f;
-+
-+    switch (p->choice) {
-+    case SPAKE_MSGTYPE_SUPPORT:
-+        free(p->u.support.groups);
-+        break;
-+    case SPAKE_MSGTYPE_CHALLENGE:
-+        ktest_empty_data(&p->u.challenge.pubkey);
-+        for (f = p->u.challenge.factors; *f != NULL; f++) {
-+            ktest_empty_spake_factor(*f);
-+            free(*f);
-+        }
-+        free(p->u.challenge.factors);
-+        break;
-+    case SPAKE_MSGTYPE_RESPONSE:
-+        ktest_empty_data(&p->u.response.pubkey);
-+        ktest_destroy_enc_data(&p->u.response.factor);
-+        break;
-+    case SPAKE_MSGTYPE_ENCDATA:
-+        ktest_destroy_enc_data(&p->u.encdata);
-+        break;
-+    default:
-+        break;
-+    }
-+    p->choice = SPAKE_MSGTYPE_UNKNOWN;
-+}
-diff --git a/src/tests/asn.1/ktest.h b/src/tests/asn.1/ktest.h
-index 493303cc8..1413cfae1 100644
---- a/src/tests/asn.1/ktest.h
-+++ b/src/tests/asn.1/ktest.h
-@@ -28,6 +28,7 @@
- #define __KTEST_H__
- 
- #include "k5-int.h"
-+#include "k5-spake.h"
- #include "kdb.h"
- 
- #define SAMPLE_USEC 123456
-@@ -124,6 +125,12 @@ void ktest_make_sample_kkdcp_message(krb5_kkdcp_message *p);
- void ktest_make_minimal_cammac(krb5_cammac *p);
- void ktest_make_maximal_cammac(krb5_cammac *p);
- void ktest_make_sample_secure_cookie(krb5_secure_cookie *p);
-+void ktest_make_minimal_spake_factor(krb5_spake_factor *p);
-+void ktest_make_maximal_spake_factor(krb5_spake_factor *p);
-+void ktest_make_support_pa_spake(krb5_pa_spake *p);
-+void ktest_make_challenge_pa_spake(krb5_pa_spake *p);
-+void ktest_make_response_pa_spake(krb5_pa_spake *p);
-+void ktest_make_encdata_pa_spake(krb5_pa_spake *p);
- 
- /*----------------------------------------------------------------------*/
- 
-@@ -209,6 +216,8 @@ void ktest_empty_ldap_seqof_key_data(krb5_context, ldap_seqof_key_data *p);
- void ktest_empty_kkdcp_message(krb5_kkdcp_message *p);
- void ktest_empty_cammac(krb5_cammac *p);
- void ktest_empty_secure_cookie(krb5_secure_cookie *p);
-+void ktest_empty_spake_factor(krb5_spake_factor *p);
-+void ktest_empty_pa_spake(krb5_pa_spake *p);
- 
- extern krb5_context test_context;
- extern char *sample_principal_name;
-diff --git a/src/tests/asn.1/ktest_equal.c b/src/tests/asn.1/ktest_equal.c
-index e8bb88944..714cc4398 100644
---- a/src/tests/asn.1/ktest_equal.c
-+++ b/src/tests/asn.1/ktest_equal.c
-@@ -853,6 +853,13 @@ ktest_equal_sequence_of_otp_tokeninfo(krb5_otp_tokeninfo **ref,
-     array_compare(ktest_equal_otp_tokeninfo);
- }
- 
-+int
-+ktest_equal_sequence_of_spake_factor(krb5_spake_factor **ref,
-+                                     krb5_spake_factor **var)
-+{
-+    array_compare(ktest_equal_spake_factor);
-+}
-+
- #ifndef DISABLE_PKINIT
- 
- static int
-@@ -1094,3 +1101,45 @@ ktest_equal_secure_cookie(krb5_secure_cookie *ref, krb5_secure_cookie *var)
-     p = p && ref->time == ref->time;
-     return p;
- }
-+
-+int
-+ktest_equal_spake_factor(krb5_spake_factor *ref, krb5_spake_factor *var)
-+{
-+    int p = TRUE;
-+    if (ref == var) return TRUE;
-+    else if (ref == NULL || var == NULL) return FALSE;
-+    p = p && scalar_equal(type);
-+    p = p && ptr_equal(data,ktest_equal_data);
-+    return p;
-+}
-+
-+int
-+ktest_equal_pa_spake(krb5_pa_spake *ref, krb5_pa_spake *var)
-+{
-+    int p = TRUE;
-+    if (ref == var) return TRUE;
-+    else if (ref == NULL || var == NULL) return FALSE;
-+    else if (ref->choice != var->choice) return FALSE;
-+    switch (ref->choice) {
-+    case SPAKE_MSGTYPE_SUPPORT:
-+        p = p && scalar_equal(u.support.ngroups);
-+        p = p && (memcmp(ref->u.support.groups,var->u.support.groups,
-+                         ref->u.support.ngroups * sizeof(int32_t)) == 0);
-+        break;
-+    case SPAKE_MSGTYPE_CHALLENGE:
-+        p = p && struct_equal(u.challenge.pubkey,ktest_equal_data);
-+        p = p && ptr_equal(u.challenge.factors,
-+                           ktest_equal_sequence_of_spake_factor);
-+        break;
-+    case SPAKE_MSGTYPE_RESPONSE:
-+        p = p && struct_equal(u.response.pubkey,ktest_equal_data);
-+        p = p && struct_equal(u.response.factor,ktest_equal_enc_data);
-+        break;
-+    case SPAKE_MSGTYPE_ENCDATA:
-+        p = p && struct_equal(u.encdata,ktest_equal_enc_data);
-+        break;
-+    default:
-+        break;
-+    }
-+    return p;
-+}
-diff --git a/src/tests/asn.1/ktest_equal.h b/src/tests/asn.1/ktest_equal.h
-index c7b5d7467..cfa82ac6e 100644
---- a/src/tests/asn.1/ktest_equal.h
-+++ b/src/tests/asn.1/ktest_equal.h
-@@ -28,6 +28,7 @@
- #define __KTEST_EQUAL_H__
- 
- #include "k5-int.h"
-+#include "k5-spake.h"
- #include "kdb.h"
- 
- /* int ktest_equal_structure(krb5_structure *ref, *var) */
-@@ -97,6 +98,8 @@ ktest_equal_sequence_of_algorithm_identifier(krb5_algorithm_identifier **ref,
-                                              krb5_algorithm_identifier **var);
- int ktest_equal_sequence_of_otp_tokeninfo(krb5_otp_tokeninfo **ref,
-                                           krb5_otp_tokeninfo **var);
-+int ktest_equal_sequence_of_spake_factor(krb5_spake_factor **ref,
-+                                         krb5_spake_factor **var);
- 
- len_array(ktest_equal_array_of_enctype,krb5_enctype);
- len_array(ktest_equal_array_of_data,krb5_data);
-@@ -152,4 +155,7 @@ int ktest_equal_cammac(krb5_cammac *ref, krb5_cammac *var);
- int ktest_equal_secure_cookie(krb5_secure_cookie *ref,
-                               krb5_secure_cookie *var);
- 
-+generic(ktest_equal_spake_factor, krb5_spake_factor);
-+generic(ktest_equal_pa_spake, krb5_pa_spake);
-+
- #endif
-diff --git a/src/tests/asn.1/make-vectors.c b/src/tests/asn.1/make-vectors.c
-index 3cb8a45ba..2fc85466b 100644
---- a/src/tests/asn.1/make-vectors.c
-+++ b/src/tests/asn.1/make-vectors.c
-@@ -40,6 +40,8 @@
- #include <PA-OTP-REQUEST.h>
- #include <PA-OTP-ENC-REQUEST.h>
- #include <AD-CAMMAC.h>
-+#include <SPAKESecondFactor.h>
-+#include <PA-SPAKE.h>
- 
- static unsigned char buf[8192];
- static size_t buf_pos;
-@@ -168,6 +170,36 @@ static struct other_verifiers overfs = { { verifiers, 2, 2 } };
- static AD_CAMMAC_t cammac_2 = { { { (void *)adlist_2, 2, 2 } },
-                                 &vmac_1, &vmac_2, &overfs };
- 
-+/* SPAKESecondFactor */
-+static SPAKESecondFactor_t factor_1 = { 1, NULL };
-+static OCTET_STRING_t factor_data = { "fdata", 5 };
-+static SPAKESecondFactor_t factor_2 = { 2, &factor_data };
-+
-+/* PA-SPAKE (support) */
-+static Int32_t group_1 = 1, group_2 = 2, *groups[] = { &group_1, &group_2 };
-+static PA_SPAKE_t pa_spake_1 = { PA_SPAKE_PR_support,
-+                                 { .support = { { groups, 2, 2 } } } };
-+
-+/* PA-SPAKE (challenge) */
-+static SPAKESecondFactor_t *factors[2] = { &factor_1, &factor_2 };
-+static PA_SPAKE_t pa_spake_2 = { PA_SPAKE_PR_challenge,
-+                                 { .challenge = { 1, { "T value", 7 },
-+                                                  { factors, 2, 2 } } } };
-+
-+/* PA-SPAKE (response) */
-+UInt32_t enctype_5 = 5;
-+static PA_SPAKE_t pa_spake_3 = { PA_SPAKE_PR_response,
-+                                 { .response = { { "S value", 7 },
-+                                                 { 0, &enctype_5,
-+                                                   { "krbASN.1 test message",
-+                                                     21 } } } } };
-+
-+/* PA-SPAKE (encdata) */
-+static PA_SPAKE_t pa_spake_4 = { PA_SPAKE_PR_encdata,
-+                                 { .encdata = { 0, &enctype_5,
-+                                                { "krbASN.1 test message",
-+                                                  21 } } } };
-+
- static int
- consume(const void *data, size_t size, void *dummy)
- {
-@@ -272,6 +304,30 @@ main()
-     der_encode(&asn_DEF_AD_CAMMAC, &cammac_2, consume, NULL);
-     printbuf();
- 
-+    printf("\nMinimal SPAKESecondFactor:\n");
-+    der_encode(&asn_DEF_SPAKESecondFactor, &factor_1, consume, NULL);
-+    printbuf();
-+
-+    printf("\nMaximal SPAKESecondFactor:\n");
-+    der_encode(&asn_DEF_SPAKESecondFactor, &factor_2, consume, NULL);
-+    printbuf();
-+
-+    printf("\nPA-SPAKE (support):\n");
-+    der_encode(&asn_DEF_PA_SPAKE, &pa_spake_1, consume, NULL);
-+    printbuf();
-+
-+    printf("\nPA-SPAKE (challenge):\n");
-+    der_encode(&asn_DEF_PA_SPAKE, &pa_spake_2, consume, NULL);
-+    printbuf();
-+
-+    printf("\nPA-SPAKE (response):\n");
-+    der_encode(&asn_DEF_PA_SPAKE, &pa_spake_3, consume, NULL);
-+    printbuf();
-+
-+    printf("\nPA-SPAKE (encdata):\n");
-+    der_encode(&asn_DEF_PA_SPAKE, &pa_spake_4, consume, NULL);
-+    printbuf();
-+
-     printf("\n");
-     return 0;
- }
-diff --git a/src/tests/asn.1/reference_encode.out b/src/tests/asn.1/reference_encode.out
-index 824e0798b..a76deead2 100644
---- a/src/tests/asn.1/reference_encode.out
-+++ b/src/tests/asn.1/reference_encode.out
-@@ -72,3 +72,9 @@ encode_krb5_kkdcp_message: 30 82 01 FC A0 82 01 EC 04 82 01 E8 6A 82 01 E4 30 82
- encode_krb5_cammac(optionals NULL): 30 12 A0 10 30 0E 30 0C A0 03 02 01 01 A1 05 04 03 61 64 31
- encode_krb5_cammac: 30 81 F2 A0 1E 30 1C 30 0C A0 03 02 01 01 A1 05 04 03 61 64 31 30 0C A0 03 02 01 02 A1 05 04 03 61 64 32 A1 3D 30 3B A0 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 03 02 01 05 A2 03 02 01 10 A3 13 30 11 A0 03 02 01 01 A1 0A 04 08 63 6B 73 75 6D 6B 64 63 A2 3D 30 3B A0 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 03 02 01 05 A2 03 02 01 10 A3 13 30 11 A0 03 02 01 01 A1 0A 04 08 63 6B 73 75 6D 73 76 63 A3 52 30 50 30 13 A3 11 30 0F A0 03 02 01 01 A1 08 04 06 63 6B 73 75 6D 31 30 39 A0 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 03 02 01 05 A2 03 02 01 10 A3 11 30 0F A0 03 02 01 01 A1 08 04 06 63 6B 73 75 6D 32
- encode_krb5_secure_cookie: 30 2C 02 04 2D F8 02 25 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61
-+encode_krb5_spake_factor(optionals NULL): 30 05 A0 03 02 01 01
-+encode_krb5_spake_factor: 30 0E A0 03 02 01 02 A1 07 04 05 66 64 61 74 61
-+encode_krb5_pa_spake(support): A0 0C 30 0A A0 08 30 06 02 01 01 02 01 02
-+encode_krb5_pa_spake(challenge): A1 2D 30 2B A0 03 02 01 01 A1 09 04 07 54 20 76 61 6C 75 65 A2 19 30 17 30 05 A0 03 02 01 01 30 0E A0 03 02 01 02 A1 07 04 05 66 64 61 74 61
-+encode_krb5_pa_spake(response): A2 34 30 32 A0 09 04 07 53 20 76 61 6C 75 65 A1 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
-+encode_krb5_pa_spake(encdata): A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65
-diff --git a/src/tests/asn.1/spake.asn1 b/src/tests/asn.1/spake.asn1
-new file mode 100644
-index 000000000..50718d8ad
---- /dev/null
-+++ b/src/tests/asn.1/spake.asn1
-@@ -0,0 +1,44 @@
-+KerberosV5SPAKE {
-+        iso(1) identified-organization(3) dod(6) internet(1)
-+        security(5) kerberosV5(2) modules(4) spake(8)
-+} DEFINITIONS EXPLICIT TAGS ::= BEGIN
-+
-+IMPORTS
-+    EncryptedData, Int32
-+      FROM KerberosV5Spec2 { iso(1) identified-organization(3)
-+        dod(6) internet(1) security(5) kerberosV5(2) modules(4)
-+        krb5spec2(2) };
-+        -- as defined in RFC 4120.
-+
-+SPAKESupport ::= SEQUENCE {
-+    groups      [0] SEQUENCE (SIZE(1..MAX)) OF Int32,
-+    ...
-+}
-+
-+SPAKEChallenge ::= SEQUENCE {
-+    group       [0] Int32,
-+    pubkey      [1] OCTET STRING,
-+    factors     [2] SEQUENCE (SIZE(1..MAX)) OF SPAKESecondFactor,
-+    ...
-+}
-+
-+SPAKESecondFactor ::= SEQUENCE {
-+    type        [0] Int32,
-+    data        [1] OCTET STRING OPTIONAL
-+}
-+
-+SPAKEResponse ::= SEQUENCE {
-+    pubkey      [0] OCTET STRING,
-+    factor      [1] EncryptedData, -- SPAKESecondFactor
-+    ...
-+}
-+
-+PA-SPAKE ::= CHOICE {
-+    support     [0] SPAKESupport,
-+    challenge   [1] SPAKEChallenge,
-+    response    [2] SPAKEResponse,
-+    encdata     [3] EncryptedData,
-+    ...
-+}
-+
-+END
-diff --git a/src/tests/asn.1/trval_reference.out b/src/tests/asn.1/trval_reference.out
-index c27a0425b..e5c715924 100644
---- a/src/tests/asn.1/trval_reference.out
-+++ b/src/tests/asn.1/trval_reference.out
-@@ -1584,3 +1584,53 @@ encode_krb5_secure_cookie:
- .  .  [Sequence/Sequence Of]
- .  .  .  [1] [Integer] 13
- .  .  .  [2] [Octet String] "pa-data"
-+
-+encode_krb5_spake_factor(optionals NULL):
-+
-+[Sequence/Sequence Of]
-+.  [0] [Integer] 1
-+
-+encode_krb5_spake_factor:
-+
-+[Sequence/Sequence Of]
-+.  [0] [Integer] 2
-+.  [1] [Octet String] "fdata"
-+
-+encode_krb5_pa_spake(support):
-+
-+[CONT 0]
-+.  [Sequence/Sequence Of]
-+.  .  [0] [Sequence/Sequence Of]
-+.  .  .  [Integer] 1
-+.  .  .  [Integer] 2
-+
-+encode_krb5_pa_spake(challenge):
-+
-+[CONT 1]
-+.  [Sequence/Sequence Of]
-+.  .  [0] [Integer] 1
-+.  .  [1] [Octet String] "T value"
-+.  .  [2] [Sequence/Sequence Of]
-+.  .  .  [Sequence/Sequence Of]
-+.  .  .  .  [0] [Integer] 1
-+.  .  .  [Sequence/Sequence Of]
-+.  .  .  .  [0] [Integer] 2
-+.  .  .  .  [1] [Octet String] "fdata"
-+
-+encode_krb5_pa_spake(response):
-+
-+[CONT 2]
-+.  [Sequence/Sequence Of]
-+.  .  [0] [Octet String] "S value"
-+.  .  [1] [Sequence/Sequence Of]
-+.  .  .  [0] [Integer] 0
-+.  .  .  [1] [Integer] 5
-+.  .  .  [2] [Octet String] "krbASN.1 test message"
-+
-+encode_krb5_pa_spake(encdata):
-+
-+[CONT 3]
-+.  [Sequence/Sequence Of]
-+.  .  [0] [Integer] 0
-+.  .  [1] [Integer] 5
-+.  .  [2] [Octet String] "krbASN.1 test message"
diff --git a/SOURCES/Add-PKINIT-KDC-support-for-freshness-token.patch b/SOURCES/Add-PKINIT-KDC-support-for-freshness-token.patch
deleted file mode 100644
index 70782fb..0000000
--- a/SOURCES/Add-PKINIT-KDC-support-for-freshness-token.patch
+++ /dev/null
@@ -1,631 +0,0 @@
-From c93112a19f73b9a984cabd320129ee8f70cb4823 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Mon, 12 Mar 2018 11:31:46 -0400
-Subject: [PATCH] Add PKINIT KDC support for freshness token
-
-Send a freshness token in the preauth hint list if PKINIT is
-configured and the request padata indicates support.  Verify the
-freshness token if the client includes one in a PKINIT request, and
-log whether one was received.  If pkinit_require_freshness is set to
-true in the realm config, reject non-anonymous requests which don't
-contain a freshness token.
-
-Add freshness token tests to t_pkinit.py with some related changes.
-Remove client long-term keys after testing password preauth so we get
-better error reporting when pkinit_require_freshness is set and a
-token is not sent.  Remove ./responder invocations for test cases
-which don't ask PKINIT responder questions, or else the responder
-would fail now that it isn't being asked for the password.  Leave
-anonymous PKINIT enabled after the anonymous tests so that we can use
-it again when testing enforcement of pkinit_require_freshness.  Add
-expected trace messages for the basic test, including one for
-receiving a freshness token.  Add minimal expected trace messages for
-the RSA test.
-
-ticket: 8648
-(cherry picked from commit 4a9050df0bc34bfb08ba24462d6e2514640f4b8e)
----
- doc/admin/conf_files/kdc_conf.rst       |   4 +
- doc/admin/pkinit.rst                    |  25 +++++
- doc/appdev/refs/macros/index.rst        |   2 +
- doc/formats/freshness_token.rst         |  19 ++++
- doc/formats/index.rst                   |   1 +
- src/include/krb5/kdcpreauth_plugin.h    |  17 ++++
- src/include/krb5/krb5.hin               |   3 +
- src/kdc/do_as_req.c                     |   2 +
- src/kdc/kdc_preauth.c                   | 130 +++++++++++++++++++++++-
- src/kdc/kdc_util.h                      |   2 +
- src/plugins/preauth/pkinit/pkinit.h     |   2 +
- src/plugins/preauth/pkinit/pkinit_srv.c |  51 +++++++++-
- src/tests/t_pkinit.py                   |  50 ++++++---
- 13 files changed, 292 insertions(+), 16 deletions(-)
- create mode 100644 doc/formats/freshness_token.rst
-
-diff --git a/doc/admin/conf_files/kdc_conf.rst b/doc/admin/conf_files/kdc_conf.rst
-index 3af1c3796..1ac1a37c2 100644
---- a/doc/admin/conf_files/kdc_conf.rst
-+++ b/doc/admin/conf_files/kdc_conf.rst
-@@ -798,6 +798,10 @@ For information about the syntax of some of these options, see
-     **pkinit_require_crl_checking** should be set to true if the
-     policy is such that up-to-date CRLs must be present for every CA.
- 
-+**pkinit_require_freshness**
-+    Specifies whether to require clients to include a freshness token
-+    in PKINIT requests.  The default value is false.  (New in release
-+    1.17.)
- 
- .. _Encryption_types:
- 
-diff --git a/doc/admin/pkinit.rst b/doc/admin/pkinit.rst
-index c601c5c9e..bec4fc800 100644
---- a/doc/admin/pkinit.rst
-+++ b/doc/admin/pkinit.rst
-@@ -327,3 +327,28 @@ appropriate :ref:`kdc_realms` subsection of the KDC's
- To obtain anonymous credentials on a client, run ``kinit -n``, or
- ``kinit -n @REALMNAME`` to specify a realm.  The resulting tickets
- will have the client name ``WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS``.
-+
-+
-+Freshness tokens
-+----------------
-+
-+Freshness tokens can ensure that the client has recently had access to
-+its certificate private key.  If freshness tokens are not required by
-+the KDC, a client program with temporary possession of the private key
-+can compose requests for future timestamps and use them later.
-+
-+In release 1.17 and later, freshness tokens are supported by the
-+client and are sent by the KDC when the client indicates support for
-+them.  Because not all clients support freshness tokens yet, they are
-+not required by default.  To check if freshness tokens are supported
-+by a realm's clients, look in the KDC logs for the lines::
-+
-+    PKINIT: freshness token received from <client principal>
-+    PKINIT: no freshness token received from <client principal>
-+
-+To require freshness tokens for all clients in a realm (except for
-+clients authenticating anonymously), set the
-+**pkinit_require_freshness** variable to ``true`` in the appropriate
-+:ref:`kdc_realms` subsection of the KDC's :ref:`kdc.conf(5)` file.  To
-+test that this option is in effect, run ``kinit -X disable_freshness``
-+and verify that authentication is unsuccessful.
-diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst
-index e76747102..dba818b26 100644
---- a/doc/appdev/refs/macros/index.rst
-+++ b/doc/appdev/refs/macros/index.rst
-@@ -181,6 +181,7 @@ Public
-    KRB5_KEYUSAGE_KRB_ERROR_CKSUM.rst
-    KRB5_KEYUSAGE_KRB_PRIV_ENCPART.rst
-    KRB5_KEYUSAGE_KRB_SAFE_CKSUM.rst
-+   KRB5_KEYUSAGE_PA_AS_FRESHNESS.rst
-    KRB5_KEYUSAGE_PA_FX_COOKIE.rst
-    KRB5_KEYUSAGE_PA_OTP_REQUEST.rst
-    KRB5_KEYUSAGE_PA_PKINIT_KX.rst
-@@ -241,6 +242,7 @@ Public
-    KRB5_PADATA_AFS3_SALT.rst
-    KRB5_PADATA_AP_REQ.rst
-    KRB5_PADATA_AS_CHECKSUM.rst
-+   KRB5_PADATA_AS_FRESHNESS.rst
-    KRB5_PADATA_ENCRYPTED_CHALLENGE.rst
-    KRB5_PADATA_ENC_SANDIA_SECURID.rst
-    KRB5_PADATA_ENC_TIMESTAMP.rst
-diff --git a/doc/formats/freshness_token.rst b/doc/formats/freshness_token.rst
-new file mode 100644
-index 000000000..3127621a9
---- /dev/null
-+++ b/doc/formats/freshness_token.rst
-@@ -0,0 +1,19 @@
-+PKINIT freshness tokens
-+=======================
-+
-+:rfc:`8070` specifies a pa-data type PA_AS_FRESHNESS, which clients
-+should reflect within signed PKINIT data to prove recent access to the
-+client certificate private key.  The contents of a freshness token are
-+left to the KDC implementation.  The MIT krb5 KDC uses the following
-+format for freshness tokens (starting in release 1.17):
-+
-+* a four-byte big-endian POSIX timestamp
-+* a four-byte big-endian key version number
-+* an :rfc:`3961` checksum, with no ASN.1 wrapper
-+
-+The checksum is computed using the first key in the local krbtgt
-+principal entry for the realm (e.g. ``krbtgt/KRBTEST.COM@KRBTEST.COM``
-+if the request is to the ``KRBTEST.COM`` realm) of the indicated key
-+version.  The checksum type must be the mandatory checksum type for
-+the encryption type of the krbtgt key.  The key usage value for the
-+checksum is 514.
-diff --git a/doc/formats/index.rst b/doc/formats/index.rst
-index 8b30626d4..4ad534424 100644
---- a/doc/formats/index.rst
-+++ b/doc/formats/index.rst
-@@ -7,3 +7,4 @@ Protocols and file formats
-    ccache_file_format
-    keytab_file_format
-    cookie
-+   freshness_token
-diff --git a/src/include/krb5/kdcpreauth_plugin.h b/src/include/krb5/kdcpreauth_plugin.h
-index f38820099..3a4754234 100644
---- a/src/include/krb5/kdcpreauth_plugin.h
-+++ b/src/include/krb5/kdcpreauth_plugin.h
-@@ -240,6 +240,23 @@ typedef struct krb5_kdcpreauth_callbacks_st {
- 
-     /* End of version 4 kdcpreauth callbacks. */
- 
-+    /*
-+     * Instruct the KDC to send a freshness token in the method data
-+     * accompanying a PREAUTH_REQUIRED or PREAUTH_FAILED error, if the client
-+     * indicated support for freshness tokens.  This callback should only be
-+     * invoked from the edata method.
-+     */
-+    void (*send_freshness_token)(krb5_context context,
-+                                 krb5_kdcpreauth_rock rock);
-+
-+    /* Validate a freshness token sent by the client.  Return 0 on success,
-+     * KRB5KDC_ERR_PREAUTH_EXPIRED on error. */
-+    krb5_error_code (*check_freshness_token)(krb5_context context,
-+                                             krb5_kdcpreauth_rock rock,
-+                                             const krb5_data *token);
-+
-+    /* End of version 5 kdcpreauth callbacks. */
-+
- } *krb5_kdcpreauth_callbacks;
- 
- /* Optional: preauth plugin initialization function. */
-diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
-index 833e72335..a650ecece 100644
---- a/src/include/krb5/krb5.hin
-+++ b/src/include/krb5/krb5.hin
-@@ -1035,7 +1035,10 @@ krb5_c_keyed_checksum_types(krb5_context context, krb5_enctype enctype,
- #define KRB5_KEYUSAGE_AS_REQ 56
- #define KRB5_KEYUSAGE_CAMMAC 64
- 
-+/* Key usage values 512-1023 are reserved for uses internal to a Kerberos
-+ * implementation. */
- #define KRB5_KEYUSAGE_PA_FX_COOKIE 513  /**< Used for encrypted FAST cookies */
-+#define KRB5_KEYUSAGE_PA_AS_FRESHNESS 514  /**< Used for freshness tokens */
- /** @} */ /* end of KRB5_KEYUSAGE group */
- 
- /**
-diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
-index 7c8da63e1..588c1375a 100644
---- a/src/kdc/do_as_req.c
-+++ b/src/kdc/do_as_req.c
-@@ -563,6 +563,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
-     state->rock.rstate = state->rstate;
-     state->rock.vctx = vctx;
-     state->rock.auth_indicators = &state->auth_indicators;
-+    state->rock.send_freshness_token = FALSE;
-     if (!state->request->client) {
-         state->status = "NULL_CLIENT";
-         errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
-@@ -659,6 +660,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
-         state->status = "GET_LOCAL_TGT";
-         goto errout;
-     }
-+    state->rock.local_tgt = state->local_tgt;
- 
-     au_state->stage = VALIDATE_POL;
- 
-diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
-index 6f34dc289..80b130222 100644
---- a/src/kdc/kdc_preauth.c
-+++ b/src/kdc/kdc_preauth.c
-@@ -87,6 +87,9 @@
- #include <assert.h>
- #include <krb5/kdcpreauth_plugin.h>
- 
-+/* Let freshness tokens be valid for ten minutes. */
-+#define FRESHNESS_LIFETIME 600
-+
- typedef struct preauth_system_st {
-     const char *name;
-     int type;
-@@ -497,8 +500,68 @@ client_name(krb5_context context, krb5_kdcpreauth_rock rock)
-     return rock->client->princ;
- }
- 
-+static void
-+send_freshness_token(krb5_context context, krb5_kdcpreauth_rock rock)
-+{
-+    rock->send_freshness_token = TRUE;
-+}
-+
-+static krb5_error_code
-+check_freshness_token(krb5_context context, krb5_kdcpreauth_rock rock,
-+                      const krb5_data *token)
-+{
-+    krb5_timestamp token_ts, now;
-+    krb5_key_data *kd;
-+    krb5_keyblock kb;
-+    krb5_kvno token_kvno;
-+    krb5_checksum cksum;
-+    krb5_data d;
-+    uint8_t *token_cksum;
-+    size_t token_cksum_len;
-+    krb5_boolean valid = FALSE;
-+    char ckbuf[4];
-+
-+    memset(&kb, 0, sizeof(kb));
-+
-+    if (krb5_timeofday(context, &now) != 0)
-+        goto cleanup;
-+
-+    if (token->length <= 8)
-+        goto cleanup;
-+    token_ts = load_32_be(token->data);
-+    token_kvno = load_32_be(token->data + 4);
-+    token_cksum = (uint8_t *)token->data + 8;
-+    token_cksum_len = token->length - 8;
-+
-+    /* Check if the token timestamp is too old. */
-+    if (ts_after(now, ts_incr(token_ts, FRESHNESS_LIFETIME)))
-+        goto cleanup;
-+
-+    /* Fetch and decrypt the local krbtgt key of the token's kvno. */
-+    if (krb5_dbe_find_enctype(context, rock->local_tgt, -1, -1, token_kvno,
-+                              &kd) != 0)
-+        goto cleanup;
-+    if (krb5_dbe_decrypt_key_data(context, NULL, kd, &kb, NULL) != 0)
-+        goto cleanup;
-+
-+    /* Verify the token checksum against the current KDC time.  The checksum
-+     * must use the mandatory checksum type of the krbtgt key's enctype. */
-+    store_32_be(token_ts, ckbuf);
-+    d = make_data(ckbuf, sizeof(ckbuf));
-+    cksum.magic = KV5M_CHECKSUM;
-+    cksum.checksum_type = 0;
-+    cksum.length = token_cksum_len;
-+    cksum.contents = token_cksum;
-+    (void)krb5_c_verify_checksum(context, &kb, KRB5_KEYUSAGE_PA_AS_FRESHNESS,
-+                                 &d, &cksum, &valid);
-+
-+cleanup:
-+    krb5_free_keyblock_contents(context, &kb);
-+    return valid ? 0 : KRB5KDC_ERR_PREAUTH_EXPIRED;
-+}
-+
- static struct krb5_kdcpreauth_callbacks_st callbacks = {
--    4,
-+    5,
-     max_time_skew,
-     client_keys,
-     free_keys,
-@@ -514,7 +577,9 @@ static struct krb5_kdcpreauth_callbacks_st callbacks = {
-     get_cookie,
-     set_cookie,
-     match_client,
--    client_name
-+    client_name,
-+    send_freshness_token,
-+    check_freshness_token
- };
- 
- static krb5_error_code
-@@ -770,6 +835,62 @@ cleanup:
-     return ret;
- }
- 
-+static krb5_error_code
-+add_freshness_token(krb5_context context, krb5_kdcpreauth_rock rock,
-+                    krb5_pa_data ***pa_list)
-+{
-+    krb5_error_code ret;
-+    krb5_timestamp now;
-+    krb5_key_data *kd;
-+    krb5_keyblock kb;
-+    krb5_checksum cksum;
-+    krb5_data d;
-+    krb5_pa_data *pa;
-+    char ckbuf[4];
-+
-+    memset(&cksum, 0, sizeof(cksum));
-+    memset(&kb, 0, sizeof(kb));
-+
-+    if (!rock->send_freshness_token)
-+        return 0;
-+    if (krb5int_find_pa_data(context, rock->request->padata,
-+                             KRB5_PADATA_AS_FRESHNESS) == NULL)
-+        return 0;
-+
-+    /* Fetch and decrypt the current local krbtgt key. */
-+    ret = krb5_dbe_find_enctype(context, rock->local_tgt, -1, -1, 0, &kd);
-+    if (ret)
-+        goto cleanup;
-+    ret = krb5_dbe_decrypt_key_data(context, NULL, kd, &kb, NULL);
-+    if (ret)
-+        goto cleanup;
-+
-+    /* Compute a checksum over the current KDC time. */
-+    ret = krb5_timeofday(context, &now);
-+    if (ret)
-+        goto cleanup;
-+    store_32_be(now, ckbuf);
-+    d = make_data(ckbuf, sizeof(ckbuf));
-+    ret = krb5_c_make_checksum(context, 0, &kb, KRB5_KEYUSAGE_PA_AS_FRESHNESS,
-+                               &d, &cksum);
-+
-+    /* Compose a freshness token from the time, krbtgt kvno, and checksum. */
-+    ret = alloc_pa_data(KRB5_PADATA_AS_FRESHNESS, 8 + cksum.length, &pa);
-+    if (ret)
-+        goto cleanup;
-+    store_32_be(now, pa->contents);
-+    store_32_be(kd->key_data_kvno, pa->contents + 4);
-+    memcpy(pa->contents + 8, cksum.contents, cksum.length);
-+
-+    /* add_pa_data_element() claims pa on success or failure. */
-+    ret = add_pa_data_element(pa_list, pa);
-+
-+cleanup:
-+    krb5_free_keyblock_contents(context, &kb);
-+    krb5_free_checksum_contents(context, &cksum);
-+    return ret;
-+}
-+
- struct hint_state {
-     kdc_hint_respond_fn respond;
-     void *arg;
-@@ -792,6 +913,11 @@ hint_list_finish(struct hint_state *state, krb5_error_code code)
-     void *oldarg = state->arg;
-     kdc_realm_t *kdc_active_realm = state->realm;
- 
-+    /* Add a freshness token if a preauth module requested it and the client
-+     * request indicates support for it. */
-+    if (!code)
-+        code = add_freshness_token(kdc_context, state->rock, &state->pa_data);
-+
-     if (!code) {
-         if (state->pa_data == NULL) {
-             krb5_klog_syslog(LOG_INFO,
-diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
-index 198eab9c4..1885c9f80 100644
---- a/src/kdc/kdc_util.h
-+++ b/src/kdc/kdc_util.h
-@@ -426,11 +426,13 @@ struct krb5_kdcpreauth_rock_st {
-     krb5_kdc_req *request;
-     krb5_data *inner_body;
-     krb5_db_entry *client;
-+    krb5_db_entry *local_tgt;
-     krb5_key_data *client_key;
-     krb5_keyblock *client_keyblock;
-     struct kdc_request_state *rstate;
-     verto_ctx *vctx;
-     krb5_data ***auth_indicators;
-+    krb5_boolean send_freshness_token;
- };
- 
- #define isflagset(flagfield, flag) (flagfield & (flag))
-diff --git a/src/plugins/preauth/pkinit/pkinit.h b/src/plugins/preauth/pkinit/pkinit.h
-index 8489a3e23..fe2ec0d31 100644
---- a/src/plugins/preauth/pkinit/pkinit.h
-+++ b/src/plugins/preauth/pkinit/pkinit.h
-@@ -77,6 +77,7 @@
- #define KRB5_CONF_PKINIT_KDC_OCSP               "pkinit_kdc_ocsp"
- #define KRB5_CONF_PKINIT_POOL                   "pkinit_pool"
- #define KRB5_CONF_PKINIT_REQUIRE_CRL_CHECKING   "pkinit_require_crl_checking"
-+#define KRB5_CONF_PKINIT_REQUIRE_FRESHNESS      "pkinit_require_freshness"
- #define KRB5_CONF_PKINIT_REVOKE                 "pkinit_revoke"
- 
- /* Make pkiDebug(fmt,...) print, or not.  */
-@@ -148,6 +149,7 @@ typedef struct _pkinit_plg_opts {
-     int allow_upn;	    /* allow UPN-SAN instead of pkinit-SAN */
-     int dh_or_rsa;	    /* selects DH or RSA based pkinit */
-     int require_crl_checking; /* require CRL for a CA (default is false) */
-+    int require_freshness;  /* require freshness token (default is false) */
-     int disable_freshness;  /* disable freshness token on client for testing */
-     int dh_min_bits;	    /* minimum DH modulus size allowed */
- } pkinit_plg_opts;
-diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
-index 8aa4d8b49..76ad5bf19 100644
---- a/src/plugins/preauth/pkinit/pkinit_srv.c
-+++ b/src/plugins/preauth/pkinit/pkinit_srv.c
-@@ -161,6 +161,10 @@ pkinit_server_get_edata(krb5_context context,
-     if (plgctx == NULL)
-         retval = EINVAL;
- 
-+    /* Send a freshness token if the client requested one. */
-+    if (!retval)
-+        cb->send_freshness_token(context, rock);
-+
-     (*respond)(arg, retval, NULL);
- }
- 
-@@ -403,6 +407,31 @@ cleanup:
-     return ret;
- }
- 
-+/* Return an error if freshness tokens are required and one was not received.
-+ * Log an appropriate message indicating whether a valid token was received. */
-+static krb5_error_code
-+check_log_freshness(krb5_context context, pkinit_kdc_context plgctx,
-+                    krb5_kdc_req *request, krb5_boolean valid_freshness_token)
-+{
-+    krb5_error_code ret;
-+    char *name = NULL;
-+
-+    ret = krb5_unparse_name(context, request->client, &name);
-+    if (ret)
-+        return ret;
-+    if (plgctx->opts->require_freshness && !valid_freshness_token) {
-+        com_err("", 0, _("PKINIT: no freshness token, rejecting auth from %s"),
-+                name);
-+        ret = KRB5KDC_ERR_PREAUTH_FAILED;
-+    } else if (valid_freshness_token) {
-+        com_err("", 0, _("PKINIT: freshness token received from %s"), name);
-+    } else {
-+        com_err("", 0, _("PKINIT: no freshness token received from %s"), name);
-+    }
-+    krb5_free_unparsed_name(context, name);
-+    return ret;
-+}
-+
- static void
- pkinit_server_verify_padata(krb5_context context,
-                             krb5_data *req_pkt,
-@@ -425,10 +454,11 @@ pkinit_server_verify_padata(krb5_context context,
-     pkinit_kdc_req_context reqctx = NULL;
-     krb5_checksum cksum = {0, 0, 0, NULL};
-     krb5_data *der_req = NULL;
--    krb5_data k5data;
-+    krb5_data k5data, *ftoken;
-     int is_signed = 1;
-     krb5_pa_data **e_data = NULL;
-     krb5_kdcpreauth_modreq modreq = NULL;
-+    krb5_boolean valid_freshness_token = FALSE;
-     char **sp;
- 
-     pkiDebug("pkinit_verify_padata: entered!\n");
-@@ -599,6 +629,14 @@ pkinit_server_verify_padata(krb5_context context,
-             goto cleanup;
-         }
- 
-+        ftoken = auth_pack->pkAuthenticator.freshnessToken;
-+        if (ftoken != NULL) {
-+            retval = cb->check_freshness_token(context, rock, ftoken);
-+            if (retval)
-+                goto cleanup;
-+            valid_freshness_token = TRUE;
-+        }
-+
-         /* check if kdcPkId present and match KDC's subjectIdentifier */
-         if (reqp->kdcPkId.data != NULL) {
-             int valid_kdcPkId = 0;
-@@ -641,6 +679,13 @@ pkinit_server_verify_padata(krb5_context context,
-         break;
-     }
- 
-+    if (is_signed) {
-+        retval = check_log_freshness(context, plgctx, request,
-+                                     valid_freshness_token);
-+        if (retval)
-+            goto cleanup;
-+    }
-+
-     if (is_signed && plgctx->auth_indicators != NULL) {
-         /* Assert configured authentication indicators. */
-         for (sp = plgctx->auth_indicators; *sp != NULL; sp++) {
-@@ -1330,6 +1375,10 @@ pkinit_init_kdc_profile(krb5_context context, pkinit_kdc_context plgctx)
-                               KRB5_CONF_PKINIT_REQUIRE_CRL_CHECKING,
-                               0, &plgctx->opts->require_crl_checking);
- 
-+    pkinit_kdcdefault_boolean(context, plgctx->realmname,
-+                              KRB5_CONF_PKINIT_REQUIRE_FRESHNESS,
-+                              0, &plgctx->opts->require_freshness);
-+
-     pkinit_kdcdefault_string(context, plgctx->realmname,
-                              KRB5_CONF_PKINIT_EKU_CHECKING,
-                              &eku_string);
-diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
-index 86fe661a0..5bc60cb1e 100755
---- a/src/tests/t_pkinit.py
-+++ b/src/tests/t_pkinit.py
-@@ -39,6 +39,8 @@ pkinit_kdc_conf = {'realms': {'$realm': {
-             'pkinit_indicator': ['indpkinit1', 'indpkinit2']}}}
- restrictive_kdc_conf = {'realms': {'$realm': {
-             'restrict_anonymous_to_tgt': 'true' }}}
-+freshness_kdc_conf = {'realms': {'$realm': {
-+            'pkinit_require_freshness': 'true'}}}
- 
- testprincs = {'krbtgt/KRBTEST.COM': {'keys': 'aes128-cts'},
-               'user': {'keys': 'aes128-cts', 'flags': '+preauth'},
-@@ -118,6 +120,10 @@ realm.kinit(realm.user_princ, password=password('user'))
- realm.klist(realm.user_princ)
- realm.run([kvno, realm.host_princ])
- 
-+# Having tested password preauth, remove the keys for better error
-+# reporting.
-+realm.run([kadminl, 'purgekeys', '-all', realm.user_princ])
-+
- # Test anonymous PKINIT.
- realm.kinit('@%s' % realm.realm, flags=['-n'], expected_code=1,
-             expected_msg='not found in Kerberos database')
-@@ -153,23 +159,32 @@ realm.run([kvno, realm.host_princ], expected_code=1,
- realm.kinit(realm.host_princ, flags=['-k'])
- realm.run([kvno, '-U', 'user', realm.host_princ])
- 
--# Go back to a normal KDC and disable anonymous PKINIT.
-+# Go back to the normal KDC environment.
- realm.stop_kdc()
- realm.start_kdc()
--realm.run([kadminl, 'delprinc', 'WELLKNOWN/ANONYMOUS'])
- 
- # Run the basic test - PKINIT with FILE: identity, with no password on the key.
--realm.run(['./responder', '-x', 'pkinit=',
--           '-X', 'X509_user_identity=%s' % file_identity, realm.user_princ])
- realm.kinit(realm.user_princ,
--            flags=['-X', 'X509_user_identity=%s' % file_identity])
-+            flags=['-X', 'X509_user_identity=%s' % file_identity],
-+            expected_trace=('Sending unauthenticated request',
-+                            '/Additional pre-authentication required',
-+                            'Preauthenticating using KDC method data',
-+                            'PKINIT client received freshness token from KDC',
-+                            'PKINIT loading CA certs and CRLs from FILE',
-+                            'PKINIT client making DH request',
-+                            'Produced preauth for next request: 133, 16',
-+                            'PKINIT client verified DH reply',
-+                            'PKINIT client found id-pkinit-san in KDC cert',
-+                            'PKINIT client matched KDC principal krbtgt/'))
- realm.klist(realm.user_princ)
- realm.run([kvno, realm.host_princ])
- 
- # Try again using RSA instead of DH.
- realm.kinit(realm.user_princ,
-             flags=['-X', 'X509_user_identity=%s' % file_identity,
--                   '-X', 'flag_RSA_PROTOCOL=yes'])
-+                   '-X', 'flag_RSA_PROTOCOL=yes'],
-+            expected_trace=('PKINIT client making RSA request',
-+                            'PKINIT client verified RSA reply'))
- realm.klist(realm.user_princ)
- 
- # Test a DH parameter renegotiation by temporarily setting a 4096-bit
-@@ -192,8 +207,23 @@ expected_trace = ('Sending unauthenticated request',
- realm.kinit(realm.user_princ,
-             flags=['-X', 'X509_user_identity=%s' % file_identity],
-             expected_trace=expected_trace)
-+
-+# Test enforcement of required freshness tokens.  (We can leave
-+# freshness tokens required after this test.)
-+realm.kinit(realm.user_princ,
-+            flags=['-X', 'X509_user_identity=%s' % file_identity,
-+                   '-X', 'disable_freshness=yes'])
-+f_env = realm.special_env('freshness', True, kdc_conf=freshness_kdc_conf)
- realm.stop_kdc()
--realm.start_kdc()
-+realm.start_kdc(env=f_env)
-+realm.kinit(realm.user_princ,
-+            flags=['-X', 'X509_user_identity=%s' % file_identity])
-+realm.kinit(realm.user_princ,
-+            flags=['-X', 'X509_user_identity=%s' % file_identity,
-+                   '-X', 'disable_freshness=yes'],
-+            expected_code=1, expected_msg='Preauthentication failed')
-+# Anonymous should never require a freshness token.
-+realm.kinit('@%s' % realm.realm, flags=['-n', '-X', 'disable_freshness=yes'])
- 
- # Run the basic test - PKINIT with FILE: identity, with a password on the key,
- # supplied by the prompter.
-@@ -229,8 +259,6 @@ shutil.copy(privkey_pem, os.path.join(path, 'user.key'))
- shutil.copy(privkey_enc_pem, os.path.join(path_enc, 'user.key'))
- shutil.copy(user_pem, os.path.join(path, 'user.crt'))
- shutil.copy(user_pem, os.path.join(path_enc, 'user.crt'))
--realm.run(['./responder', '-x', 'pkinit=', '-X',
--           'X509_user_identity=%s' % dir_identity, realm.user_princ])
- realm.kinit(realm.user_princ,
-             flags=['-X', 'X509_user_identity=%s' % dir_identity])
- realm.klist(realm.user_princ)
-@@ -262,8 +290,6 @@ realm.klist(realm.user_princ)
- realm.run([kvno, realm.host_princ])
- 
- # PKINIT with PKCS12: identity, with no password on the bundle.
--realm.run(['./responder', '-x', 'pkinit=',
--           '-X', 'X509_user_identity=%s' % p12_identity, realm.user_princ])
- realm.kinit(realm.user_princ,
-             flags=['-X', 'X509_user_identity=%s' % p12_identity])
- realm.klist(realm.user_princ)
-@@ -357,8 +383,6 @@ conf = open(softpkcs11rc, 'w')
- conf.write("%s\t%s\t%s\t%s\n" % ('user', 'user token', user_pem, privkey_pem))
- conf.close()
- # Expect to succeed without having to supply any more information.
--realm.run(['./responder', '-x', 'pkinit=',
--           '-X', 'X509_user_identity=%s' % p11_identity, realm.user_princ])
- realm.kinit(realm.user_princ,
-             flags=['-X', 'X509_user_identity=%s' % p11_identity])
- realm.klist(realm.user_princ)
diff --git a/SOURCES/Add-PKINIT-client-support-for-freshness-token.patch b/SOURCES/Add-PKINIT-client-support-for-freshness-token.patch
deleted file mode 100644
index 1a00819..0000000
--- a/SOURCES/Add-PKINIT-client-support-for-freshness-token.patch
+++ /dev/null
@@ -1,336 +0,0 @@
-From 5edc6de93196b4f07da6695a4b271a067000c84d Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Tue, 31 Jan 2017 17:02:34 -0500
-Subject: [PATCH] Add PKINIT client support for freshness token
-
-Send an empty PA_AS_FRESHNESS padata item in unauthenticated AS
-requests to indicate support for RFC 8070.  If the KDC includes a
-PA_AS_FRESHNESS value in its method data, echo it back in the new
-freshnessToken field of pkAuthenticator
-
-ticket: 8648
-(cherry picked from commit 085785362e01467cb25c79a90dcebfba9ea019d8)
----
- doc/user/user_commands/kinit.rst          |  3 +++
- src/include/k5-int-pkinit.h               |  1 +
- src/include/krb5/krb5.hin                 |  1 +
- src/lib/krb5/asn.1/asn1_k_encode.c        |  5 ++++-
- src/lib/krb5/krb/get_in_tkt.c             | 12 ++++++++----
- src/lib/krb5/krb/init_creds_ctx.h         |  2 +-
- src/plugins/preauth/pkinit/pkinit.h       |  3 +++
- src/plugins/preauth/pkinit/pkinit_clnt.c  | 19 ++++++++++++++++++-
- src/plugins/preauth/pkinit/pkinit_lib.c   |  3 +++
- src/plugins/preauth/pkinit/pkinit_trace.h |  2 ++
- src/tests/asn.1/ktest.c                   |  4 ++++
- src/tests/asn.1/pkinit_encode.out         |  2 +-
- src/tests/asn.1/pkinit_trval.out          |  1 +
- 13 files changed, 50 insertions(+), 8 deletions(-)
-
-diff --git a/doc/user/user_commands/kinit.rst b/doc/user/user_commands/kinit.rst
-index 3f9d5340f..1f696920f 100644
---- a/doc/user/user_commands/kinit.rst
-+++ b/doc/user/user_commands/kinit.rst
-@@ -197,6 +197,9 @@ OPTIONS
-         specify use of RSA, rather than the default Diffie-Hellman
-         protocol
- 
-+    **disable_freshness**\ [**=yes**]
-+        disable sending freshness tokens (for testing purposes only)
-+
- 
- ENVIRONMENT
- -----------
-diff --git a/src/include/k5-int-pkinit.h b/src/include/k5-int-pkinit.h
-index 7b2f595cb..4622a629e 100644
---- a/src/include/k5-int-pkinit.h
-+++ b/src/include/k5-int-pkinit.h
-@@ -42,6 +42,7 @@ typedef struct _krb5_pk_authenticator {
-     krb5_timestamp  ctime;
-     krb5_int32      nonce;  /* (0..4294967295) */
-     krb5_checksum   paChecksum;
-+    krb5_data      *freshnessToken;
- } krb5_pk_authenticator;
- 
- /* PKAuthenticator draft9 */
-diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
-index e81bb0a6d..833e72335 100644
---- a/src/include/krb5/krb5.hin
-+++ b/src/include/krb5/krb5.hin
-@@ -1879,6 +1879,7 @@ krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype,
- #define KRB5_PADATA_OTP_PIN_CHANGE      144 /**< RFC 6560 section 4.3 */
- #define KRB5_PADATA_PKINIT_KX           147 /**< RFC 6112 */
- #define KRB5_ENCPADATA_REQ_ENC_PA_REP   149 /**< RFC 6806 */
-+#define KRB5_PADATA_AS_FRESHNESS        150 /**< RFC 8070 */
- 
- #define KRB5_SAM_USE_SAD_AS_KEY         0x80000000
- #define KRB5_SAM_SEND_ENCRYPTED_SAD     0x40000000
-diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c
-index 889460989..3b23fe34a 100644
---- a/src/lib/krb5/asn.1/asn1_k_encode.c
-+++ b/src/lib/krb5/asn.1/asn1_k_encode.c
-@@ -1442,9 +1442,12 @@ DEFFIELD(pk_authenticator_1, krb5_pk_authenticator, ctime, 1, kerberos_time);
- DEFFIELD(pk_authenticator_2, krb5_pk_authenticator, nonce, 2, int32);
- DEFFIELD(pk_authenticator_3, krb5_pk_authenticator, paChecksum, 3,
-          ostring_checksum);
-+DEFFIELD(pk_authenticator_4, krb5_pk_authenticator, freshnessToken, 4,
-+         opt_ostring_data_ptr);
- static const struct atype_info *pk_authenticator_fields[] = {
-     &k5_atype_pk_authenticator_0, &k5_atype_pk_authenticator_1,
--    &k5_atype_pk_authenticator_2, &k5_atype_pk_authenticator_3
-+    &k5_atype_pk_authenticator_2, &k5_atype_pk_authenticator_3,
-+    &k5_atype_pk_authenticator_4
- };
- DEFSEQTYPE(pk_authenticator, krb5_pk_authenticator, pk_authenticator_fields);
- 
-diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
-index 47a00bf2c..1d96ff163 100644
---- a/src/lib/krb5/krb/get_in_tkt.c
-+++ b/src/lib/krb5/krb/get_in_tkt.c
-@@ -895,7 +895,7 @@ krb5_init_creds_init(krb5_context context,
-     ctx->request = k5alloc(sizeof(krb5_kdc_req), &code);
-     if (code != 0)
-         goto cleanup;
--    ctx->enc_pa_rep_permitted = TRUE;
-+    ctx->info_pa_permitted = TRUE;
-     code = krb5_copy_principal(context, client, &ctx->request->client);
-     if (code != 0)
-         goto cleanup;
-@@ -1389,7 +1389,11 @@ init_creds_step_request(krb5_context context,
-         krb5_free_data(context, ctx->encoded_previous_request);
-         ctx->encoded_previous_request = NULL;
-     }
--    if (ctx->enc_pa_rep_permitted) {
-+    if (ctx->info_pa_permitted) {
-+        code = add_padata(&ctx->request->padata, KRB5_PADATA_AS_FRESHNESS,
-+                          NULL, 0);
-+        if (code)
-+            goto cleanup;
-         code = add_padata(&ctx->request->padata, KRB5_ENCPADATA_REQ_ENC_PA_REP,
-                           NULL, 0);
-     }
-@@ -1530,7 +1534,7 @@ init_creds_step_reply(krb5_context context,
-                    ctx->selected_preauth_type == KRB5_PADATA_NONE) {
-             /* The KDC didn't like our informational padata (probably a pre-1.7
-              * MIT krb5 KDC).  Retry without it. */
--            ctx->enc_pa_rep_permitted = FALSE;
-+            ctx->info_pa_permitted = FALSE;
-             ctx->restarted = TRUE;
-             code = restart_init_creds_loop(context, ctx, FALSE);
-         } else if (reply_code == KDC_ERR_PREAUTH_EXPIRED) {
-@@ -1574,7 +1578,7 @@ init_creds_step_reply(krb5_context context,
-                 goto cleanup;
-             /* Reset per-realm negotiation state. */
-             ctx->restarted = FALSE;
--            ctx->enc_pa_rep_permitted = TRUE;
-+            ctx->info_pa_permitted = TRUE;
-             code = restart_init_creds_loop(context, ctx, FALSE);
-         } else {
-             if (retry && ctx->selected_preauth_type != KRB5_PADATA_NONE) {
-diff --git a/src/lib/krb5/krb/init_creds_ctx.h b/src/lib/krb5/krb/init_creds_ctx.h
-index fe769685b..b19410a13 100644
---- a/src/lib/krb5/krb/init_creds_ctx.h
-+++ b/src/lib/krb5/krb/init_creds_ctx.h
-@@ -58,7 +58,7 @@ struct _krb5_init_creds_context {
-     krb5_data s2kparams;
-     krb5_keyblock as_key;
-     krb5_enctype etype;
--    krb5_boolean enc_pa_rep_permitted;
-+    krb5_boolean info_pa_permitted;
-     krb5_boolean restarted;
-     struct krb5_responder_context_st rctx;
-     krb5_preauthtype selected_preauth_type;
-diff --git a/src/plugins/preauth/pkinit/pkinit.h b/src/plugins/preauth/pkinit/pkinit.h
-index f3de9ad7a..8489a3e23 100644
---- a/src/plugins/preauth/pkinit/pkinit.h
-+++ b/src/plugins/preauth/pkinit/pkinit.h
-@@ -148,6 +148,7 @@ typedef struct _pkinit_plg_opts {
-     int allow_upn;	    /* allow UPN-SAN instead of pkinit-SAN */
-     int dh_or_rsa;	    /* selects DH or RSA based pkinit */
-     int require_crl_checking; /* require CRL for a CA (default is false) */
-+    int disable_freshness;  /* disable freshness token on client for testing */
-     int dh_min_bits;	    /* minimum DH modulus size allowed */
- } pkinit_plg_opts;
- 
-@@ -162,6 +163,7 @@ typedef struct _pkinit_req_opts {
-     int require_crl_checking;
-     int dh_size;	    /* initial request DH modulus size (default=1024) */
-     int require_hostname_match;
-+    int disable_freshness;
- } pkinit_req_opts;
- 
- /*
-@@ -214,6 +216,7 @@ struct _pkinit_req_context {
-     int identity_initialized;
-     int identity_prompted;
-     krb5_error_code identity_prompt_retval;
-+    krb5_data *freshness_token;
- };
- typedef struct _pkinit_req_context *pkinit_req_context;
- 
-diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c
-index f1bc6b21d..9483d69e5 100644
---- a/src/plugins/preauth/pkinit/pkinit_clnt.c
-+++ b/src/plugins/preauth/pkinit/pkinit_clnt.c
-@@ -231,6 +231,8 @@ pkinit_as_req_create(krb5_context context,
-         auth_pack.pkAuthenticator.cusec = cusec;
-         auth_pack.pkAuthenticator.nonce = nonce;
-         auth_pack.pkAuthenticator.paChecksum = *cksum;
-+        if (!reqctx->opts->disable_freshness)
-+            auth_pack.pkAuthenticator.freshnessToken = reqctx->freshness_token;
-         auth_pack.clientDHNonce.length = 0;
-         auth_pack.clientPublicValue = &info;
-         auth_pack.supportedKDFs = (krb5_data **)supported_kdf_alg_ids;
-@@ -1162,6 +1164,7 @@ pkinit_client_process(krb5_context context, krb5_clpreauth_moddata moddata,
-     pkinit_context plgctx = (pkinit_context)moddata;
-     pkinit_req_context reqctx = (pkinit_req_context)modreq;
-     krb5_keyblock as_key;
-+    krb5_data d;
- 
-     pkiDebug("pkinit_client_process %p %p %p %p\n",
-              context, plgctx, reqctx, request);
-@@ -1174,6 +1177,12 @@ pkinit_client_process(krb5_context context, krb5_clpreauth_moddata moddata,
-     case KRB5_PADATA_PKINIT_KX:
-         reqctx->rfc6112_kdc = 1;
-         return 0;
-+    case KRB5_PADATA_AS_FRESHNESS:
-+        TRACE_PKINIT_CLIENT_FRESHNESS_TOKEN(context);
-+        krb5_free_data(context, reqctx->freshness_token);
-+        reqctx->freshness_token = NULL;
-+        d = make_data(in_padata->contents, in_padata->length);
-+        return krb5_copy_data(context, &d, &reqctx->freshness_token);
-     case KRB5_PADATA_PK_AS_REQ:
-         reqctx->rfc4556_kdc = 1;
-         pkiDebug("processing KRB5_PADATA_PK_AS_REQ\n");
-@@ -1359,7 +1368,7 @@ cleanup:
- static int
- pkinit_client_get_flags(krb5_context kcontext, krb5_preauthtype patype)
- {
--    if (patype == KRB5_PADATA_PKINIT_KX)
-+    if (patype == KRB5_PADATA_PKINIT_KX || patype == KRB5_PADATA_AS_FRESHNESS)
-         return PA_INFO;
-     return PA_REAL;
- }
-@@ -1376,6 +1385,7 @@ static krb5_preauthtype supported_client_pa_types[] = {
-     KRB5_PADATA_PK_AS_REP_OLD,
-     KRB5_PADATA_PK_AS_REQ_OLD,
-     KRB5_PADATA_PKINIT_KX,
-+    KRB5_PADATA_AS_FRESHNESS,
-     0
- };
- 
-@@ -1400,6 +1410,7 @@ pkinit_client_req_init(krb5_context context,
-     reqctx->opts = NULL;
-     reqctx->idctx = NULL;
-     reqctx->idopts = NULL;
-+    reqctx->freshness_token = NULL;
- 
-     retval = pkinit_init_req_opts(&reqctx->opts);
-     if (retval)
-@@ -1410,6 +1421,7 @@ pkinit_client_req_init(krb5_context context,
-     reqctx->opts->dh_or_rsa = plgctx->opts->dh_or_rsa;
-     reqctx->opts->allow_upn = plgctx->opts->allow_upn;
-     reqctx->opts->require_crl_checking = plgctx->opts->require_crl_checking;
-+    reqctx->opts->disable_freshness = plgctx->opts->disable_freshness;
- 
-     retval = pkinit_init_req_crypto(&reqctx->cryptoctx);
-     if (retval)
-@@ -1468,6 +1480,8 @@ pkinit_client_req_fini(krb5_context context, krb5_clpreauth_moddata moddata,
-     if (reqctx->idopts != NULL)
-         pkinit_fini_identity_opts(reqctx->idopts);
- 
-+    krb5_free_data(context, reqctx->freshness_token);
-+
-     free(reqctx);
-     return;
- }
-@@ -1580,6 +1594,9 @@ handle_gic_opt(krb5_context context,
-             pkiDebug("Setting flag to use RSA_PROTOCOL\n");
-             plgctx->opts->dh_or_rsa = RSA_PROTOCOL;
-         }
-+    } else if (strcmp(attr, "disable_freshness") == 0) {
-+        if (strcmp(value, "yes") == 0)
-+            plgctx->opts->disable_freshness = 1;
-     }
-     return 0;
- }
-diff --git a/src/plugins/preauth/pkinit/pkinit_lib.c b/src/plugins/preauth/pkinit/pkinit_lib.c
-index 2f88545da..d5858c424 100644
---- a/src/plugins/preauth/pkinit/pkinit_lib.c
-+++ b/src/plugins/preauth/pkinit/pkinit_lib.c
-@@ -82,6 +82,8 @@ pkinit_init_plg_opts(pkinit_plg_opts **plgopts)
-     opts->dh_or_rsa = DH_PROTOCOL;
-     opts->allow_upn = 0;
-     opts->require_crl_checking = 0;
-+    opts->require_freshness = 0;
-+    opts->disable_freshness = 0;
- 
-     opts->dh_min_bits = PKINIT_DEFAULT_DH_MIN_BITS;
- 
-@@ -145,6 +147,7 @@ free_krb5_auth_pack(krb5_auth_pack **in)
-         free((*in)->clientPublicValue);
-     }
-     free((*in)->pkAuthenticator.paChecksum.contents);
-+    krb5_free_data(NULL, (*in)->pkAuthenticator.freshnessToken);
-     if ((*in)->supportedCMSTypes != NULL)
-         free_krb5_algorithm_identifiers(&((*in)->supportedCMSTypes));
-     if ((*in)->supportedKDFs) {
-diff --git a/src/plugins/preauth/pkinit/pkinit_trace.h b/src/plugins/preauth/pkinit/pkinit_trace.h
-index 2d95da94a..7f95206c0 100644
---- a/src/plugins/preauth/pkinit/pkinit_trace.h
-+++ b/src/plugins/preauth/pkinit/pkinit_trace.h
-@@ -41,6 +41,8 @@
-     TRACE(c, "PKINIT client found no acceptable EKU in KDC cert")
- #define TRACE_PKINIT_CLIENT_EKU_SKIP(c)                                 \
-     TRACE(c, "PKINIT client skipping EKU check due to configuration")
-+#define TRACE_PKINIT_CLIENT_FRESHNESS_TOKEN(c)                  \
-+    TRACE(c, "PKINIT client received freshness token from KDC")
- #define TRACE_PKINIT_CLIENT_KDF_ALG(c, kdf, keyblock)                   \
-     TRACE(c, "PKINIT client used KDF {hexdata} to compute reply key "   \
-           "{keyblock}", kdf, keyblock)
-diff --git a/src/tests/asn.1/ktest.c b/src/tests/asn.1/ktest.c
-index 43084cbbd..cf63f3f66 100644
---- a/src/tests/asn.1/ktest.c
-+++ b/src/tests/asn.1/ktest.c
-@@ -725,6 +725,8 @@ ktest_make_sample_pk_authenticator(krb5_pk_authenticator *p)
-     ktest_make_sample_checksum(&p->paChecksum);
-     /* We don't encode the checksum type, only the contents. */
-     p->paChecksum.checksum_type = 0;
-+    p->freshnessToken = ealloc(sizeof(krb5_data));
-+    ktest_make_sample_data(p->freshnessToken);
- }
- 
- static void
-@@ -1651,6 +1653,8 @@ ktest_empty_pk_authenticator(krb5_pk_authenticator *p)
- {
-     ktest_empty_checksum(&p->paChecksum);
-     p->paChecksum.contents = NULL;
-+    krb5_free_data(NULL, p->freshnessToken);
-+    p->freshnessToken = NULL;
- }
- 
- static void
-diff --git a/src/tests/asn.1/pkinit_encode.out b/src/tests/asn.1/pkinit_encode.out
-index 463128de0..3b0f7190a 100644
---- a/src/tests/asn.1/pkinit_encode.out
-+++ b/src/tests/asn.1/pkinit_encode.out
-@@ -4,7 +4,7 @@ encode_krb5_pa_pk_as_rep(dhInfo): A0 28 30 26 80 08 6B 72 62 35 64 61 74 61 A1 0
- encode_krb5_pa_pk_as_rep(encKeyPack): 81 08 6B 72 62 35 64 61 74 61
- encode_krb5_pa_pk_as_rep_draft9(dhSignedData): 80 08 6B 72 62 35 64 61 74 61
- encode_krb5_pa_pk_as_rep_draft9(encKeyPack): 81 08 6B 72 62 35 64 61 74 61
--encode_krb5_auth_pack: 30 81 93 A0 29 30 27 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 06 04 04 31 32 33 34 A1 22 30 20 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 03 09 00 6B 72 62 35 64 61 74 61 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61
-+encode_krb5_auth_pack: 30 81 9F A0 35 30 33 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 06 04 04 31 32 33 34 A4 0A 04 08 6B 72 62 35 64 61 74 61 A1 22 30 20 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 03 09 00 6B 72 62 35 64 61 74 61 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61
- encode_krb5_auth_pack_draft9: 30 75 A0 4F 30 4D A0 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 05 02 03 01 E2 40 A3 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A4 03 02 01 2A A1 22 30 20 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 03 09 00 6B 72 62 35 64 61 74 61
- encode_krb5_kdc_dh_key_info: 30 25 A0 0B 03 09 00 6B 72 62 35 64 61 74 61 A1 03 02 01 2A A2 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A
- encode_krb5_reply_key_pack: 30 26 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34
-diff --git a/src/tests/asn.1/pkinit_trval.out b/src/tests/asn.1/pkinit_trval.out
-index 58d870631..f9edbe154 100644
---- a/src/tests/asn.1/pkinit_trval.out
-+++ b/src/tests/asn.1/pkinit_trval.out
-@@ -57,6 +57,7 @@ encode_krb5_auth_pack:
- .  .  [1] [Generalized Time] "19940610060317Z"
- .  .  [2] [Integer] 42
- .  .  [3] [Octet String] "1234"
-+.  .  [4] [Octet String] "krb5data"
- .  [1] [Sequence/Sequence Of]
- .  .  [Sequence/Sequence Of]
- .  .  .  [Object Identifier] <9>
diff --git a/SOURCES/Add-SPAKE-preauth-support.patch b/SOURCES/Add-SPAKE-preauth-support.patch
deleted file mode 100644
index ab04539..0000000
--- a/SOURCES/Add-SPAKE-preauth-support.patch
+++ /dev/null
@@ -1,14349 +0,0 @@
-From f8f2cff0aba6ea7dd9b5fef89549aaff36ce4fee Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Fri, 25 Sep 2015 17:47:35 -0400
-Subject: [PATCH] Add SPAKE preauth support
-
-This is an implementation of draft-ietf-kitten-krb-spake-preauth-05.
-SPAKE preauth authenticates using the client principal long-term key,
-but protects against offline dictionary attacks.
-
-SPAKE preauth negotiates a group for use by the SPAKE2 algorithm.  The
-edwards25519 group is implemented using code adapted from BoringSSL.
-The P-256, P-384, and P-521 groups are implemented against OpenSSL.
-edwards25519 is enabled by default on the client; no groups are
-enabled by default on the KDC.
-
-SPAKE preauth can also include a second factor.  Second factor support
-isn't included in this implementation; comments have been left to
-indicate what should change when it is added in.
-
-Integration tests (tests/t_spake.py) are included with good coverage
-of the negotiation scenarios.
-
-Test vectors from the draft are checked against the group's "result"
-operation.  The "keygen" operation is inherently random and is
-therefore not tested against the vectors, but is effectively exercised
-by the integration tests.
-
-KDC optimistic challenge is implemented.  In the future we should
-implement client optimistic SPAKE as well; this will require changes
-to the generic client preauth framework.
-
-In the future we should add per-realm configuration to deny encrypted
-timestamp and encrypted challenge on a per-realm basis.  This
-configuration should stick across client realm referrals.
-
-In the future we should avoid attempting encrypting timestamp or
-encrypted challenge if the KDC replies to a single-factor
-SPAKEResponse message with PREAUTH_FAILED.  This will require a change
-to the generic client preauth framework.
-
-In the future we should make SPAKE support apply to the Windows build,
-either by adding support for building plugin DLLs or by moving the
-edwards25519 and client code to libkrb5.
-
-[npmccallum@redhat.com: split up internal headers; split out group
-registry contents; implemented P-384 and P-521]
-
-ticket: 8647 (new)
-(cherry picked from commit 7447259401569c92b1fb2e31cb02edbbffd67d35)
----
- NOTICE                                        |   51 +
- doc/admin/conf_files/kdc_conf.rst             |   22 +-
- doc/admin/conf_files/krb5_conf.rst            |   15 +
- doc/admin/index.rst                           |    1 +
- doc/admin/spake.rst                           |   46 +
- doc/formats/cookie.rst                        |   37 +
- doc/notice.rst                                |   47 +
- src/Makefile.in                               |    2 +
- src/config/pre.in                             |    6 +
- src/configure.in                              |   20 +
- src/include/k5-int.h                          |    3 +
- src/include/krb5/krb5.hin                     |    2 +
- src/kdc/kdc_preauth.c                         |    2 +
- src/lib/krb5/krb/preauth2.c                   |    2 +
- src/lib/krb5/os/trace.c                       |    1 +
- src/plugins/preauth/spake/AUTHORS             |   16 +
- src/plugins/preauth/spake/Makefile.in         |   39 +
- src/plugins/preauth/spake/deps                |   73 +
- src/plugins/preauth/spake/edwards25519.c      | 2651 ++++++
- .../preauth/spake/edwards25519_tables.h       | 7881 +++++++++++++++++
- src/plugins/preauth/spake/groups.c            |  442 +
- src/plugins/preauth/spake/groups.h            |  148 +
- src/plugins/preauth/spake/iana.c              |  108 +
- src/plugins/preauth/spake/iana.h              |   65 +
- src/plugins/preauth/spake/openssl.c           |  315 +
- src/plugins/preauth/spake/spake.exports       |    2 +
- src/plugins/preauth/spake/spake_client.c      |  363 +
- src/plugins/preauth/spake/spake_kdc.c         |  590 ++
- src/plugins/preauth/spake/t_krb5.conf         |    2 +
- src/plugins/preauth/spake/t_vectors.c         |  476 +
- src/plugins/preauth/spake/trace.h             |   74 +
- src/plugins/preauth/spake/util.c              |  211 +
- src/plugins/preauth/spake/util.h              |   56 +
- src/tests/Makefile.in                         |    1 +
- src/tests/t_spake.py                          |  151 +
- 35 files changed, 13917 insertions(+), 4 deletions(-)
- create mode 100644 doc/admin/spake.rst
- create mode 100644 src/plugins/preauth/spake/AUTHORS
- create mode 100644 src/plugins/preauth/spake/Makefile.in
- create mode 100644 src/plugins/preauth/spake/deps
- create mode 100644 src/plugins/preauth/spake/edwards25519.c
- create mode 100644 src/plugins/preauth/spake/edwards25519_tables.h
- create mode 100644 src/plugins/preauth/spake/groups.c
- create mode 100644 src/plugins/preauth/spake/groups.h
- create mode 100644 src/plugins/preauth/spake/iana.c
- create mode 100644 src/plugins/preauth/spake/iana.h
- create mode 100644 src/plugins/preauth/spake/openssl.c
- create mode 100644 src/plugins/preauth/spake/spake.exports
- create mode 100644 src/plugins/preauth/spake/spake_client.c
- create mode 100644 src/plugins/preauth/spake/spake_kdc.c
- create mode 100644 src/plugins/preauth/spake/t_krb5.conf
- create mode 100644 src/plugins/preauth/spake/t_vectors.c
- create mode 100644 src/plugins/preauth/spake/trace.h
- create mode 100644 src/plugins/preauth/spake/util.c
- create mode 100644 src/plugins/preauth/spake/util.h
- create mode 100644 src/tests/t_spake.py
-
-diff --git a/NOTICE b/NOTICE
-index 1f2ce6493..cb6ab462b 100644
---- a/NOTICE
-+++ b/NOTICE
-@@ -1316,3 +1316,54 @@ The following notice applies to
-    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.
-+
-+======================================================================
-+
-+The following notice applies to portions of
-+"src/plugins/preauth/spake/edwards25519.c" and
-+"src/plugins/preauth/spake/edwards25519_tables.h":
-+
-+The MIT License (MIT)
-+
-+Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS
-+file).
-+
-+Permission is hereby granted, free of charge, to any person obtaining
-+a copy of this software and associated documentation files (the
-+"Software"), to deal in the Software without restriction, including
-+without limitation the rights to use, copy, modify, merge, publish,
-+distribute, sublicense, and/or sell copies of the Software, and to
-+permit persons to whom the Software is furnished to do so, subject to
-+the following conditions:
-+
-+The above copyright notice and this permission notice shall be
-+included in all copies or substantial portions of the Software.
-+
-+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-+
-+======================================================================
-+
-+The following notice applies to portions of
-+"src/plugins/preauth/spake/edwards25519.c":
-+
-+Copyright (c) 2015-2016, Google Inc.
-+
-+Permission to use, copy, modify, and/or distribute this software for
-+any purpose with or without fee is hereby granted, provided that the
-+above copyright notice and this permission notice appear in all
-+copies.
-+
-+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
-+WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
-+WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
-+AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
-+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
-+PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-+PERFORMANCE OF THIS SOFTWARE.
-diff --git a/doc/admin/conf_files/kdc_conf.rst b/doc/admin/conf_files/kdc_conf.rst
-index 1ac1a37c2..f8cf1be7c 100644
---- a/doc/admin/conf_files/kdc_conf.rst
-+++ b/doc/admin/conf_files/kdc_conf.rst
-@@ -43,10 +43,10 @@ The kdc.conf file may contain the following sections:
- [kdcdefaults]
- ~~~~~~~~~~~~~
- 
--With two exceptions, relations in the [kdcdefaults] section specify
--default values for realm variables, to be used if the [realms]
--subsection does not contain a relation for the tag.  See the
--:ref:`kdc_realms` section for the definitions of these relations.
-+Some relations in the [kdcdefaults] section specify default values for
-+realm variables, to be used if the [realms] subsection does not
-+contain a relation for the tag.  See the :ref:`kdc_realms` section for
-+the definitions of these relations.
- 
- * **host_based_services**
- * **kdc_listen**
-@@ -56,6 +56,8 @@ subsection does not contain a relation for the tag.  See the
- * **no_host_referral**
- * **restrict_anonymous_to_tgt**
- 
-+The following [kdcdefaults] variables have no per-realm equivalent:
-+
- **kdc_max_dgram_reply_size**
-     Specifies the maximum packet size that can be sent over UDP.  The
-     default value is 4096 bytes.
-@@ -65,6 +67,12 @@ subsection does not contain a relation for the tag.  See the
-     daemon.  The value may be limited by OS settings.  The default
-     value is 5.
- 
-+**spake_preauth_kdc_challenge**
-+    (String.)  Specifies the group for a SPAKE optimistic challenge.
-+    See the **spake_preauth_groups** variable in :ref:`libdefaults`
-+    for possible values.  The default is not to issue an optimistic
-+    challenge.  (New in release 1.17.)
-+
- 
- .. _kdc_realms:
- 
-@@ -403,6 +411,12 @@ The following tags may be specified in a [realms] subsection:
-     without allowing anonymous authentication to services.  The
-     default value is false.  New in release 1.9.
- 
-+**spake_preauth_indicator**
-+    (String.)  Specifies an authentication indicator value that the
-+    KDC asserts into tickets obtained using SPAKE pre-authentication.
-+    The default is not to add any indicators.  This option may be
-+    specified multiple times.  New in release 1.17.
-+
- **supported_enctypes**
-     (List of *key*:*salt* strings.)  Specifies the default key/salt
-     combinations of principals for this realm.  Any principals created
-diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
-index 3d33dba40..2574e5c26 100644
---- a/doc/admin/conf_files/krb5_conf.rst
-+++ b/doc/admin/conf_files/krb5_conf.rst
-@@ -367,6 +367,21 @@ The libdefaults section may contain any of the following relations:
-     with the session key type.  See the **kdc_req_checksum_type**
-     configuration option for the possible values and their meanings.
- 
-+**spake_preauth_groups**
-+    A whitespace or comma-separated list of words which specifies the
-+    groups allowed for SPAKE preauthentication.  The possible values
-+    are:
-+
-+    ============ ================================
-+    edwards25519 Edwards25519 curve (:rfc:`7748`)
-+    P-256        NIST P-256 curve (:rfc:`5480`)
-+    P-384        NIST P-384 curve (:rfc:`5480`)
-+    P-521        NIST P-521 curve (:rfc:`5480`)
-+    ============ ================================
-+
-+    The default value for the client is ``edwards25519``.  The default
-+    value for the KDC is empty.  New in release 1.17.
-+
- **ticket_lifetime**
-     (:ref:`duration` string.)  Sets the default lifetime for initial
-     ticket requests.  The default value is 1 day.
-diff --git a/doc/admin/index.rst b/doc/admin/index.rst
-index b702f4021..292a64104 100644
---- a/doc/admin/index.rst
-+++ b/doc/admin/index.rst
-@@ -15,6 +15,7 @@ For administrators
-    backup_host.rst
-    pkinit.rst
-    otp.rst
-+   spake.rst
-    princ_dns.rst
-    enctypes.rst
-    https.rst
-diff --git a/doc/admin/spake.rst b/doc/admin/spake.rst
-new file mode 100644
-index 000000000..b65c694aa
---- /dev/null
-+++ b/doc/admin/spake.rst
-@@ -0,0 +1,46 @@
-+SPAKE Preauthentication
-+=======================
-+
-+SPAKE preauthentication (added in release 1.17) uses public key
-+cryptography techniques to protect against password dictionary
-+attacks.  Unlike :ref:`PKINIT <pkinit>`, it does not require any
-+additional infrastructure such as certificates; it simply needs to be
-+turned on.  Using SPAKE preauthentication may modestly increase the
-+CPU and network load on the KDC.
-+
-+SPAKE preauthentication can use one of four elliptic curve groups for
-+its password-authenticated key exchange.  The recommended group is
-+``edwards25519``; three NIST curves (``P-256``, ``P-384``, and
-+``P-521``) are also supported.
-+
-+By default, SPAKE with the ``edwards25519`` group is enabled on
-+clients, but the KDC does not offer SPAKE by default.  To turn it on,
-+set the **spake_preauth_groups** variable in :ref:`libdefaults` to a
-+list of allowed groups.  This variable affects both the client and the
-+KDC.  Simply setting it to ``edwards25519`` is recommended::
-+
-+    [libdefaults]
-+        spake_preauth_groups = edwards25519
-+
-+Set the **+requires_preauth** and **-allow_svr** flags on client
-+principal entries, as you would for any preauthentication mechanism::
-+
-+    kadmin: modprinc +requires_preauth -allow_srv PRINCNAME
-+
-+Clients which do not implement SPAKE preauthentication will fall back
-+to encrypted timestamp.
-+
-+By default, SPAKE preauthentication requires an extra network round
-+trip to the KDC during initial authentication.  If most of the clients
-+in a realm support SPAKE, this extra round trip can be eliminated
-+using an optimistic challenge, by setting the
-+**spake_preauth_kdc_challenge** variable in :ref:`kdcdefaults` to a
-+single group name::
-+
-+    [kdcdefaults]
-+        spake_preauth_kdc_challenge = edwards25519
-+
-+Using optimistic challenge will cause the KDC to do extra work for
-+initial authentication requests that do not result in SPAKE
-+preauthentication, but will save work when SPAKE preauthentication is
-+used.
-diff --git a/doc/formats/cookie.rst b/doc/formats/cookie.rst
-index 640955c90..e32365daa 100644
---- a/doc/formats/cookie.rst
-+++ b/doc/formats/cookie.rst
-@@ -58,3 +58,40 @@ mechanisms which have separate request and reply types, the request
- type is used; this allows the KDC to determine whether a cookie is
- relevant to a request by comparing the request pa-data types to the
- cookie data types.
-+
-+SPAKE cookie format (version 1)
-+-------------------------------
-+
-+Inside the SecureCookie wrapper, a data value of type 151 contains
-+state for SPAKE pre-authentication.  This data is the concatenation of
-+the following:
-+
-+* a two-byte big-endian version number with the value 1
-+* a two-byte big-endian stage number
-+* a four-byte big-endian group number
-+* a four-byte big-endian length and data for the SPAKE value
-+* a four-byte big-endian length and data for the transcript hash
-+* zero or more second factor records, each consisting of:
-+  - a four-byte big-endian second-factor type
-+  - a four-byte big-endian length and data
-+
-+The stage value is 0 if the cookie was sent with a challenge message.
-+Otherwise it is 1 for the first encdata message sent by the KDC during
-+an exchange, 2 for the second, etc..
-+
-+The group value indicates the group number used in the SPAKE challenge.
-+
-+For a stage-0 cookie, the SPAKE value is the KDC private key,
-+represented in the scalar marshalling form of the group.  For other
-+cookies, the SPAKE value is the SPAKE result K, represented in the
-+group element marshalling form.
-+
-+For a stage-0 cookie, the transcript hash is the intermediate hash
-+after updating with the client support message (if one was sent) and
-+challenge.  For other cookies it is the final hash.
-+
-+For a stage-0 cookie, there may be any number of second-factor
-+records, including none; a second-factor type need not create a state
-+field if it does not need one, and no record is created for SF-NONE.
-+For other cookies, there must be exactly one second-factor record
-+corresponding to the factor type chosen by the client.
-diff --git a/doc/notice.rst b/doc/notice.rst
-index a32e55529..8f6b68638 100644
---- a/doc/notice.rst
-+++ b/doc/notice.rst
-@@ -1237,3 +1237,50 @@ The following notice applies to
-     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.
-+
-+-------------------
-+
-+The following notice applies to portions of
-+``src/plugins/preauth/spake/edwards25519.c`` and
-+``src/plugins/preauth/spake/edwards25519_tables.h``:
-+
-+The MIT License (MIT)
-+
-+Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file).
-+
-+Permission is hereby granted, free of charge, to any person obtaining a copy
-+of this software and associated documentation files (the "Software"), to
-+deal in the Software without restriction, including without limitation the
-+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-+sell copies of the Software, and to permit persons to whom the Software is
-+furnished to do so, subject to the following conditions:
-+
-+The above copyright notice and this permission notice shall be included in
-+all copies or substantial portions of the Software.
-+
-+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+IN THE SOFTWARE.
-+
-+-------------------
-+
-+The following notice applies to portions of
-+``src/plugins/preauth/spake/edwards25519.c``:
-+
-+Copyright (c) 2015-2016, Google Inc.
-+
-+Permission to use, copy, modify, and/or distribute this software for any
-+purpose with or without fee is hereby granted, provided that the above
-+copyright notice and this permission notice appear in all copies.
-+
-+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-+SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-+OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-diff --git a/src/Makefile.in b/src/Makefile.in
-index ac9a2a060..77beff8bc 100644
---- a/src/Makefile.in
-+++ b/src/Makefile.in
-@@ -25,6 +25,7 @@ SUBDIRS=util include lib \
- 	plugins/kdcpolicy/test \
- 	plugins/preauth/otp \
- 	plugins/preauth/pkinit \
-+	plugins/preauth/spake \
- 	plugins/preauth/test \
- 	plugins/tls/k5tls \
- 	kdc kadmin slave clients appl tests \
-@@ -523,6 +524,7 @@ pyrunenv.vals: Makefile
- 	done > $@
- 	echo "tls_impl = '$(TLS_IMPL)'" >> $@
- 	echo "have_sasl = '$(HAVE_SASL)'" >> $@
-+	echo "have_spake_openssl = '$(HAVE_SPAKE_OPENSSL)'" >> $@
- 	echo "sizeof_time_t = $(SIZEOF_TIME_T)" >> $@
- 
- runenv.py: pyrunenv.vals
-diff --git a/src/config/pre.in b/src/config/pre.in
-index 03f5c8890..6317d3564 100644
---- a/src/config/pre.in
-+++ b/src/config/pre.in
-@@ -441,9 +441,15 @@ TLS_IMPL	= @TLS_IMPL@
- TLS_IMPL_CFLAGS = @TLS_IMPL_CFLAGS@
- TLS_IMPL_LIBS	= @TLS_IMPL_LIBS@
- 
-+# SPAKE preauth back-end libraries
-+SPAKE_OPENSSL_LIBS = @SPAKE_OPENSSL_LIBS@
-+
- # Whether we have the SASL header file for the LDAP KDB module
- HAVE_SASL = @HAVE_SASL@
- 
-+# Whether we are building support for NIST SPAKE groups using OpenSSL
-+HAVE_SPAKE_OPENSSL = @HAVE_SPAKE_OPENSSL@
-+
- # Whether we have libresolv 1.1.5 for URI discovery tests
- HAVE_RESOLV_WRAPPER = @HAVE_RESOLV_WRAPPER@
- 
-diff --git a/src/configure.in b/src/configure.in
-index 2b6d5baa7..08c63beca 100644
---- a/src/configure.in
-+++ b/src/configure.in
-@@ -321,6 +321,25 @@ AC_SUBST(TLS_IMPL)
- AC_SUBST(TLS_IMPL_CFLAGS)
- AC_SUBST(TLS_IMPL_LIBS)
- 
-+# The SPAKE preauth plugin currently supports edwards25519 natively,
-+# and can support three NIST groups using OpenSSL.
-+HAVE_SPAKE_OPENSSL=no
-+AC_ARG_WITH([spake-openssl],
-+AC_HELP_STRING([--with-spake-openssl],
-+               [use OpenSSL for SPAKE preauth @<:@auto@:>@]),,[withval=auto])
-+if test "$withval" = auto -o "$withval" = yes; then
-+  AC_CHECK_LIB([crypto],[EC_POINT_new],[have_crypto=true],[have_crypto=false])
-+  if test "$have_crypto" = true; then
-+    AC_DEFINE(SPAKE_OPENSSL,1,[Define to use OpenSSL for SPAKE preauth])
-+    SPAKE_OPENSSL_LIBS=-lcrypto
-+    HAVE_SPAKE_OPENSSL=yes
-+  elif test "$withval" = yes; then
-+    AC_MSG_ERROR([OpenSSL libcrypto not found])
-+  fi
-+fi
-+AC_SUBST(HAVE_SPAKE_OPENSSL)
-+AC_SUBST(SPAKE_OPENSSL_LIBS)
-+
- AC_ARG_ENABLE([aesni],
- AC_HELP_STRING([--disable-aesni],[Do not build with AES-NI support]), ,
- enable_aesni=check)
-@@ -1440,6 +1459,7 @@ dnl	ccapi ccapi/lib ccapi/lib/unix ccapi/server ccapi/server/unix ccapi/test
- 	plugins/kdb/test
- 	plugins/kdcpolicy/test
- 	plugins/preauth/otp
-+	plugins/preauth/spake
- 	plugins/preauth/test
- 	plugins/authdata/greet_client
- 	plugins/authdata/greet_server
-diff --git a/src/include/k5-int.h b/src/include/k5-int.h
-index 69b81a7f7..86b53c76b 100644
---- a/src/include/k5-int.h
-+++ b/src/include/k5-int.h
-@@ -286,6 +286,9 @@ typedef unsigned char   u_char;
- #define KRB5_CONF_RESTRICT_ANONYMOUS_TO_TGT    "restrict_anonymous_to_tgt"
- #define KRB5_CONF_SAFE_CHECKSUM_TYPE           "safe_checksum_type"
- #define KRB5_CONF_SUPPORTED_ENCTYPES           "supported_enctypes"
-+#define KRB5_CONF_SPAKE_PREAUTH_INDICATOR      "spake_preauth_indicator"
-+#define KRB5_CONF_SPAKE_PREAUTH_KDC_CHALLENGE  "spake_preauth_kdc_challenge"
-+#define KRB5_CONF_SPAKE_PREAUTH_GROUPS         "spake_preauth_groups"
- #define KRB5_CONF_TICKET_LIFETIME              "ticket_lifetime"
- #define KRB5_CONF_UDP_PREFERENCE_LIMIT         "udp_preference_limit"
- #define KRB5_CONF_UNLOCKITER                   "unlockiter"
-diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
-index a650ecece..cea22dcac 100644
---- a/src/include/krb5/krb5.hin
-+++ b/src/include/krb5/krb5.hin
-@@ -1034,6 +1034,7 @@ krb5_c_keyed_checksum_types(krb5_context context, krb5_enctype enctype,
- #define KRB5_KEYUSAGE_ENC_CHALLENGE_KDC 55
- #define KRB5_KEYUSAGE_AS_REQ 56
- #define KRB5_KEYUSAGE_CAMMAC 64
-+#define KRB5_KEYUSAGE_SPAKE 65
- 
- /* Key usage values 512-1023 are reserved for uses internal to a Kerberos
-  * implementation. */
-@@ -1883,6 +1884,7 @@ krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype,
- #define KRB5_PADATA_PKINIT_KX           147 /**< RFC 6112 */
- #define KRB5_ENCPADATA_REQ_ENC_PA_REP   149 /**< RFC 6806 */
- #define KRB5_PADATA_AS_FRESHNESS        150 /**< RFC 8070 */
-+#define KRB5_PADATA_SPAKE               151
- 
- #define KRB5_SAM_USE_SAD_AS_KEY         0x80000000
- #define KRB5_SAM_SEND_ENCRYPTED_SAD     0x40000000
-diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
-index 62ff9a8a7..86b9e2991 100644
---- a/src/kdc/kdc_preauth.c
-+++ b/src/kdc/kdc_preauth.c
-@@ -131,6 +131,8 @@ get_plugin_vtables(krb5_context context,
-                            "preauth");
-     k5_plugin_register_dyn(context, PLUGIN_INTERFACE_KDCPREAUTH, "otp",
-                            "preauth");
-+    k5_plugin_register_dyn(context, PLUGIN_INTERFACE_KDCPREAUTH, "spake",
-+                           "preauth");
-     k5_plugin_register(context, PLUGIN_INTERFACE_KDCPREAUTH,
-                        "encrypted_challenge",
-                        kdcpreauth_encrypted_challenge_initvt);
-diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c
-index 6b96fa135..451e0b7a8 100644
---- a/src/lib/krb5/krb/preauth2.c
-+++ b/src/lib/krb5/krb/preauth2.c
-@@ -132,6 +132,8 @@ k5_init_preauth_context(krb5_context context)
-     /* Auto-register built-in modules. */
-     k5_plugin_register_dyn(context, PLUGIN_INTERFACE_CLPREAUTH, "pkinit",
-                            "preauth");
-+    k5_plugin_register_dyn(context, PLUGIN_INTERFACE_CLPREAUTH, "spake",
-+                           "preauth");
-     k5_plugin_register(context, PLUGIN_INTERFACE_CLPREAUTH,
-                        "encrypted_challenge",
-                        clpreauth_encrypted_challenge_initvt);
-diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
-index 10b4f0c14..40a9e7b10 100644
---- a/src/lib/krb5/os/trace.c
-+++ b/src/lib/krb5/os/trace.c
-@@ -163,6 +163,7 @@ padata_type_string(krb5_preauthtype type)
-     case KRB5_PADATA_PKINIT_KX: return "PA-PKINIT-KX";
-     case KRB5_ENCPADATA_REQ_ENC_PA_REP: return "PA-REQ-ENC-PA-REP";
-     case KRB5_PADATA_AS_FRESHNESS: return "PA_AS_FRESHNESS";
-+    case KRB5_PADATA_SPAKE: return "PA-SPAKE";
-     default: return NULL;
-     }
- }
-diff --git a/src/plugins/preauth/spake/AUTHORS b/src/plugins/preauth/spake/AUTHORS
-new file mode 100644
-index 000000000..31d71c211
---- /dev/null
-+++ b/src/plugins/preauth/spake/AUTHORS
-@@ -0,0 +1,16 @@
-+# This is the official list of fiat-crypto authors for copyright purposes.
-+# This file is distinct from the CONTRIBUTORS files.
-+# See the latter for an explanation.
-+
-+# Names should be added to this file as one of
-+#     Organization's name
-+#     Individual's name <submission email address>
-+#     Individual's name <submission email address> <email2> <emailN>
-+# See CONTRIBUTORS for the meaning of multiple email addresses.
-+
-+# Please keep the list sorted.
-+
-+Andres Erbsen <andreser@mit.edu>
-+Google Inc.
-+Jade Philipoom <jadep@mit.edu> <jade.philipoom@gmail.com>
-+Massachusetts Institute of Technology
-diff --git a/src/plugins/preauth/spake/Makefile.in b/src/plugins/preauth/spake/Makefile.in
-new file mode 100644
-index 000000000..dd1b90730
---- /dev/null
-+++ b/src/plugins/preauth/spake/Makefile.in
-@@ -0,0 +1,39 @@
-+mydir=plugins$(S)preauth$(S)spake
-+BUILDTOP=$(REL)..$(S)..$(S)..
-+MODULE_INSTALL_DIR = $(KRB5_PA_MODULE_DIR)
-+
-+# Like RUN_TEST, but use t_krb5.conf from this directory.
-+RUN_TEST_LOCAL_CONF=$(RUN_SETUP) KRB5_CONFIG=$(srcdir)/t_krb5.conf LC_ALL=C \
-+	$(VALGRIND)
-+
-+LIBBASE=spake
-+LIBMAJOR=0
-+LIBMINOR=0
-+RELDIR=../plugins/preauth/spake
-+SHLIB_EXPDEPS=$(KRB5_BASE_DEPLIBS)
-+SHLIB_EXPLIBS=$(KRB5_BASE_LIBS) $(SPAKE_OPENSSL_LIBS)
-+
-+STLIBOBJS=util.o iana.o groups.o openssl.o edwards25519.o \
-+	spake_client.o spake_kdc.o
-+
-+SRCS= \
-+	$(srcdir)/util.c \
-+	$(srcdir)/iana.c \
-+	$(srcdir)/groups.c \
-+	$(srcdir)/openssl.c \
-+	$(srcdir)/edwards25519.c \
-+	$(srcdir)/spake_client.c \
-+	$(srcdir)/spake_kdc.c
-+
-+t_vectors: t_vectors.o $(STLIBOBJS) $(SHLIB_EXPDEPS)
-+	$(CC_LINK) -o $@ t_vectors.o $(STLIBOBJS) $(SHLIB_EXPLIBS)
-+
-+all-unix: all-liblinks
-+install-unix: install-libs
-+clean-unix:: clean-liblinks clean-libs clean-libobjs
-+
-+check-unix: t_vectors
-+	$(RUN_TEST_LOCAL_CONF) ./t_vectors
-+
-+@libnover_frag@
-+@libobj_frag@
-diff --git a/src/plugins/preauth/spake/deps b/src/plugins/preauth/spake/deps
-new file mode 100644
-index 000000000..ce636af66
---- /dev/null
-+++ b/src/plugins/preauth/spake/deps
-@@ -0,0 +1,73 @@
-+#
-+# Generated makefile dependencies follow.
-+#
-+util.so util.po $(OUTPRE)util.$(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 groups.h iana.h \
-+  trace.h util.c util.h
-+iana.so iana.po $(OUTPRE)iana.$(OBJEXT): iana.c iana.h
-+groups.so groups.po $(OUTPRE)groups.$(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 groups.c groups.h \
-+  iana.h trace.h
-+openssl.so openssl.po $(OUTPRE)openssl.$(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 groups.h iana.h \
-+  openssl.c
-+edwards25519.so edwards25519.po $(OUTPRE)edwards25519.$(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 \
-+  edwards25519.c edwards25519_tables.h groups.h iana.h
-+spake_client.so spake_client.po $(OUTPRE)spake_client.$(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-spake.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/clpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \
-+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
-+  groups.h iana.h spake_client.c trace.h util.h
-+spake_kdc.so spake_kdc.po $(OUTPRE)spake_kdc.$(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-input.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-spake.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/kdcpreauth_plugin.h \
-+  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
-+  $(top_srcdir)/include/socket-utils.h groups.h iana.h \
-+  spake_kdc.c trace.h util.h
-diff --git a/src/plugins/preauth/spake/edwards25519.c b/src/plugins/preauth/spake/edwards25519.c
-new file mode 100644
-index 000000000..fd228d9d4
---- /dev/null
-+++ b/src/plugins/preauth/spake/edwards25519.c
-@@ -0,0 +1,2651 @@
-+/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-+/* This file is adapted from the SPAKE edwards25519 code in BoringSSL. */
-+/*
-+ * The MIT License (MIT)
-+ *
-+ * Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file).
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this software and associated documentation files (the "Software"), to
-+ * deal in the Software without restriction, including without limitation the
-+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-+ * sell copies of the Software, and to permit persons to whom the Software is
-+ * furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ */
-+/*
-+ * Copyright (c) 2015-2016, Google Inc.
-+ *
-+ * Permission to use, copy, modify, and/or distribute this software for any
-+ * purpose with or without fee is hereby granted, provided that the above
-+ * copyright notice and this permission notice appear in all copies.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-+ */
-+
-+/*
-+ * This code is adapted from the BoringSSL edwards25519 SPAKE2 implementation
-+ * from third_party/fiat and crypto/spake25519.c, with the following
-+ * adaptations:
-+ *
-+ * - The M and N points are the ones from draft-irtf-cfrg-spake2-05.  The
-+ *   BoringSSL M and N points were determined similarly, but were not
-+ *   restricted to members of the generator subgroup, so they use only one hash
-+ *   iteration for both points.  The intent in BoringSSL had been to multiply w
-+ *   by the cofactor so that wM and wN would be in the subgroup, but as that
-+ *   step was accidentally omitted, a hack had to be introduced after the fact
-+ *   to add multiples of the prime order to the scalar.  That hack is not
-+ *   present in this code, and the SPAKE preauth spec does not multiply w by
-+ *   the cofactor as it is unnecessary if M and N are chosen from the subgroup.
-+ *
-+ * - The SPAKE code is modified to fit the groups.h interface and the SPAKE
-+ *   preauth spec.
-+ *
-+ * - The required declarations and code are all here in one file (except for
-+ *   the generator point table, which is still in a separate header), so all of
-+ *   the functions are declared static.
-+ *
-+ * - BORINGSSL_CURVE25519_64BIT is defined here using preprocessor conditionals
-+ *   derived from the BoringSSL headers.
-+ *
-+ * - The field element bounds assertion checks are disabled by default, as they
-+ *   slow the code down by roughly a factor of two.  The
-+ *   OPENSSL_COMPILE_ASSERT() in fe_copy_lt() is changed to a regular assert
-+ *   and is also conditionalized.  Do a build and "make check" with
-+ *   EDWARDS25519_ASSERTS defined when updating this code.
-+ *
-+ * - The copyright comments at the top are formatted the way we do so in other
-+ *   source files, for ease of extraction.
-+ *
-+ * - Declarations in for loops conflict with our compiler configuration in
-+ *   older versions of gcc, so they are moved outside of the for loop.
-+ *
-+ * - The preprocessor symbol OPENSSL_SMALL is changed to CONFIG_SMALL.
-+ *
-+ * - OPENSSL_memset and OPENSSL_memmove are changed to memset and memmove, in
-+ *   each case verifying that they are used with nonzero length arguments.
-+ *
-+ * - CRYPTO_memcmp is changed to k5_bcmp.
-+ *
-+ * - Functions used only by X25519 or Ed25519 interfaces but not SPAKE are
-+ *   removed, taking care to check for unused functions in both the 64-bit and
-+ *   32-bit preprocessor branches.  ge_p3_dbl() is unused here if CONFIG_SMALL
-+ *   is defined, so it is placed inside #ifndef CONFIG_SMALL.
-+ */
-+
-+// Some of this code is taken from the ref10 version of Ed25519 in SUPERCOP
-+// 20141124 (http://bench.cr.yp.to/supercop.html). That code is released as
-+// public domain but parts have been replaced with code generated by Fiat
-+// (https://github.com/mit-plv/fiat-crypto), which is MIT licensed.
-+
-+#include "groups.h"
-+#include "iana.h"
-+
-+#ifdef __GNUC__
-+#pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
-+#endif
-+
-+/*
-+ * These preprocessor conditionals are derived the BoringSSL
-+ * include/openssl/base.h (OPENSSL_64_BIT) and crypto/internal.h
-+ * (BORINGSSL_HAS_UINT128).
-+ */
-+#if defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64) || defined(__aarch64__) || ((defined(__PPC64__) || defined(__powerpc64__)) && defined(_LITTLE_ENDIAN)) || defined(__mips__) && defined(__LP64__)
-+#if !defined(_MSC_VER) || defined(__clang__)
-+#define BORINGSSL_CURVE25519_64BIT
-+typedef __int128_t int128_t;
-+typedef __uint128_t uint128_t;
-+#endif
-+#endif
-+
-+#ifndef EDWARDS25519_ASSERTS
-+#define assert_fe(f)
-+#define assert_fe_loose(f)
-+#define assert_fe_frozen(f)
-+#endif
-+
-+/* From BoringSSL third-party/fiat/internal.h */
-+
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+// fe means field element. Here the field is \Z/(2^255-19). An element t,
-+// entries t[0]...t[4], represents the integer t[0]+2^51 t[1]+2^102 t[2]+2^153
-+// t[3]+2^204 t[4].
-+// fe limbs are bounded by 1.125*2^51.
-+// Multiplication and carrying produce fe from fe_loose.
-+typedef struct fe { uint64_t v[5]; } fe;
-+
-+// fe_loose limbs are bounded by 3.375*2^51.
-+// Addition and subtraction produce fe_loose from (fe, fe).
-+typedef struct fe_loose { uint64_t v[5]; } fe_loose;
-+#else
-+// fe means field element. Here the field is \Z/(2^255-19). An element t,
-+// entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
-+// t[3]+2^102 t[4]+...+2^230 t[9].
-+// fe limbs are bounded by 1.125*2^26,1.125*2^25,1.125*2^26,1.125*2^25,etc.
-+// Multiplication and carrying produce fe from fe_loose.
-+typedef struct fe { uint32_t v[10]; } fe;
-+
-+// fe_loose limbs are bounded by 3.375*2^26,3.375*2^25,3.375*2^26,3.375*2^25,etc.
-+// Addition and subtraction produce fe_loose from (fe, fe).
-+typedef struct fe_loose { uint32_t v[10]; } fe_loose;
-+#endif
-+
-+// ge means group element.
-+//
-+// Here the group is the set of pairs (x,y) of field elements (see fe.h)
-+// satisfying -x^2 + y^2 = 1 + d x^2y^2
-+// where d = -121665/121666.
-+//
-+// Representations:
-+//   ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
-+//   ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
-+//   ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
-+//   ge_precomp (Duif): (y+x,y-x,2dxy)
-+
-+typedef struct {
-+  fe X;
-+  fe Y;
-+  fe Z;
-+} ge_p2;
-+
-+typedef struct {
-+  fe X;
-+  fe Y;
-+  fe Z;
-+  fe T;
-+} ge_p3;
-+
-+typedef struct {
-+  fe_loose X;
-+  fe_loose Y;
-+  fe_loose Z;
-+  fe_loose T;
-+} ge_p1p1;
-+
-+typedef struct {
-+  fe_loose yplusx;
-+  fe_loose yminusx;
-+  fe_loose xy2d;
-+} ge_precomp;
-+
-+typedef struct {
-+  fe_loose YplusX;
-+  fe_loose YminusX;
-+  fe_loose Z;
-+  fe_loose T2d;
-+} ge_cached;
-+
-+#include "edwards25519_tables.h"
-+
-+/* From BoringSSL third-party/fiat/curve25519.c */
-+
-+static uint64_t load_3(const uint8_t *in) {
-+  uint64_t result;
-+  result = (uint64_t)in[0];
-+  result |= ((uint64_t)in[1]) << 8;
-+  result |= ((uint64_t)in[2]) << 16;
-+  return result;
-+}
-+
-+static uint64_t load_4(const uint8_t *in) {
-+  uint64_t result;
-+  result = (uint64_t)in[0];
-+  result |= ((uint64_t)in[1]) << 8;
-+  result |= ((uint64_t)in[2]) << 16;
-+  result |= ((uint64_t)in[3]) << 24;
-+  return result;
-+}
-+
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+static uint64_t load_8(const uint8_t *in) {
-+  uint64_t result;
-+  result = (uint64_t)in[0];
-+  result |= ((uint64_t)in[1]) << 8;
-+  result |= ((uint64_t)in[2]) << 16;
-+  result |= ((uint64_t)in[3]) << 24;
-+  result |= ((uint64_t)in[4]) << 32;
-+  result |= ((uint64_t)in[5]) << 40;
-+  result |= ((uint64_t)in[6]) << 48;
-+  result |= ((uint64_t)in[7]) << 56;
-+  return result;
-+}
-+
-+static uint8_t /*bool*/ addcarryx_u51(uint8_t /*bool*/ c, uint64_t a,
-+                                      uint64_t b, uint64_t *low) {
-+  // This function extracts 51 bits of result and 1 bit of carry (52 total), so
-+  // a 64-bit intermediate is sufficient.
-+  uint64_t x = a + b + c;
-+  *low = x & ((UINT64_C(1) << 51) - 1);
-+  return (x >> 51) & 1;
-+}
-+
-+static uint8_t /*bool*/ subborrow_u51(uint8_t /*bool*/ c, uint64_t a,
-+                                      uint64_t b, uint64_t *low) {
-+  // This function extracts 51 bits of result and 1 bit of borrow (52 total), so
-+  // a 64-bit intermediate is sufficient.
-+  uint64_t x = a - b - c;
-+  *low = x & ((UINT64_C(1) << 51) - 1);
-+  return x >> 63;
-+}
-+
-+static uint64_t cmovznz64(uint64_t t, uint64_t z, uint64_t nz) {
-+  t = -!!t; // all set if nonzero, 0 if 0
-+  return (t&nz) | ((~t)&z);
-+}
-+
-+#else
-+
-+static uint8_t /*bool*/ addcarryx_u25(uint8_t /*bool*/ c, uint32_t a,
-+                                      uint32_t b, uint32_t *low) {
-+  // This function extracts 25 bits of result and 1 bit of carry (26 total), so
-+  // a 32-bit intermediate is sufficient.
-+  uint32_t x = a + b + c;
-+  *low = x & ((1 << 25) - 1);
-+  return (x >> 25) & 1;
-+}
-+
-+static uint8_t /*bool*/ addcarryx_u26(uint8_t /*bool*/ c, uint32_t a,
-+                                      uint32_t b, uint32_t *low) {
-+  // This function extracts 26 bits of result and 1 bit of carry (27 total), so
-+  // a 32-bit intermediate is sufficient.
-+  uint32_t x = a + b + c;
-+  *low = x & ((1 << 26) - 1);
-+  return (x >> 26) & 1;
-+}
-+
-+static uint8_t /*bool*/ subborrow_u25(uint8_t /*bool*/ c, uint32_t a,
-+                                      uint32_t b, uint32_t *low) {
-+  // This function extracts 25 bits of result and 1 bit of borrow (26 total), so
-+  // a 32-bit intermediate is sufficient.
-+  uint32_t x = a - b - c;
-+  *low = x & ((1 << 25) - 1);
-+  return x >> 31;
-+}
-+
-+static uint8_t /*bool*/ subborrow_u26(uint8_t /*bool*/ c, uint32_t a,
-+                                      uint32_t b, uint32_t *low) {
-+  // This function extracts 26 bits of result and 1 bit of borrow (27 total), so
-+  // a 32-bit intermediate is sufficient.
-+  uint32_t x = a - b - c;
-+  *low = x & ((1 << 26) - 1);
-+  return x >> 31;
-+}
-+
-+static uint32_t cmovznz32(uint32_t t, uint32_t z, uint32_t nz) {
-+  t = -!!t; // all set if nonzero, 0 if 0
-+  return (t&nz) | ((~t)&z);
-+}
-+
-+#endif
-+
-+
-+// Field operations.
-+
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+
-+#ifdef EDWARDS25519_ASSERTS
-+#define assert_fe(f) do { \
-+  unsigned _assert_fe_i; \
-+  for (_assert_fe_i = 0; _assert_fe_i< 5; _assert_fe_i++) { \
-+    assert(f[_assert_fe_i] < 1.125*(UINT64_C(1)<<51)); \
-+  } \
-+} while (0)
-+
-+#define assert_fe_loose(f) do { \
-+  unsigned _assert_fe_i; \
-+  for (_assert_fe_i = 0; _assert_fe_i< 5; _assert_fe_i++) { \
-+    assert(f[_assert_fe_i] < 3.375*(UINT64_C(1)<<51)); \
-+  } \
-+} while (0)
-+
-+#define assert_fe_frozen(f) do { \
-+  unsigned _assert_fe_i; \
-+  for (_assert_fe_i = 0; _assert_fe_i< 5; _assert_fe_i++) { \
-+    assert(f[_assert_fe_i] < (UINT64_C(1)<<51)); \
-+  } \
-+} while (0)
-+#endif /* EDWARDS25519_ASSERTS */
-+
-+static void fe_frombytes_impl(uint64_t h[5], const uint8_t *s) {
-+  // Ignores top bit of s.
-+  uint64_t a0 = load_8(s);
-+  uint64_t a1 = load_8(s+8);
-+  uint64_t a2 = load_8(s+16);
-+  uint64_t a3 = load_8(s+24);
-+  // Use 51 bits, 64-51 = 13 left.
-+  h[0] = a0 & ((UINT64_C(1) << 51) - 1);
-+  // (64-51) + 38 = 13 + 38 = 51
-+  h[1] = (a0 >> 51) | ((a1 & ((UINT64_C(1) << 38) - 1)) << 13);
-+  // (64-38) + 25 = 26 + 25 = 51
-+  h[2] = (a1 >> 38) | ((a2 & ((UINT64_C(1) << 25) - 1)) << 26);
-+  // (64-25) + 12 = 39 + 12 = 51
-+  h[3] = (a2 >> 25) | ((a3 & ((UINT64_C(1) << 12) - 1)) << 39);
-+  // (64-12) = 52, ignore top bit
-+  h[4] = (a3 >> 12) & ((UINT64_C(1) << 51) - 1);
-+  assert_fe(h);
-+}
-+
-+static void fe_frombytes(fe *h, const uint8_t *s) {
-+  fe_frombytes_impl(h->v, s);
-+}
-+
-+static void fe_freeze(uint64_t out[5], const uint64_t in1[5]) {
-+  { const uint64_t x7 = in1[4];
-+  { const uint64_t x8 = in1[3];
-+  { const uint64_t x6 = in1[2];
-+  { const uint64_t x4 = in1[1];
-+  { const uint64_t x2 = in1[0];
-+  { uint64_t x10; uint8_t/*bool*/ x11 = subborrow_u51(0x0, x2, 0x7ffffffffffed, &x10);
-+  { uint64_t x13; uint8_t/*bool*/ x14 = subborrow_u51(x11, x4, 0x7ffffffffffff, &x13);
-+  { uint64_t x16; uint8_t/*bool*/ x17 = subborrow_u51(x14, x6, 0x7ffffffffffff, &x16);
-+  { uint64_t x19; uint8_t/*bool*/ x20 = subborrow_u51(x17, x8, 0x7ffffffffffff, &x19);
-+  { uint64_t x22; uint8_t/*bool*/ x23 = subborrow_u51(x20, x7, 0x7ffffffffffff, &x22);
-+  { uint64_t x24 = cmovznz64(x23, 0x0, 0xffffffffffffffffL);
-+  { uint64_t x25 = (x24 & 0x7ffffffffffed);
-+  { uint64_t x27; uint8_t/*bool*/ x28 = addcarryx_u51(0x0, x10, x25, &x27);
-+  { uint64_t x29 = (x24 & 0x7ffffffffffff);
-+  { uint64_t x31; uint8_t/*bool*/ x32 = addcarryx_u51(x28, x13, x29, &x31);
-+  { uint64_t x33 = (x24 & 0x7ffffffffffff);
-+  { uint64_t x35; uint8_t/*bool*/ x36 = addcarryx_u51(x32, x16, x33, &x35);
-+  { uint64_t x37 = (x24 & 0x7ffffffffffff);
-+  { uint64_t x39; uint8_t/*bool*/ x40 = addcarryx_u51(x36, x19, x37, &x39);
-+  { uint64_t x41 = (x24 & 0x7ffffffffffff);
-+  { uint64_t x43; addcarryx_u51(x40, x22, x41, &x43);
-+  out[0] = x27;
-+  out[1] = x31;
-+  out[2] = x35;
-+  out[3] = x39;
-+  out[4] = x43;
-+  }}}}}}}}}}}}}}}}}}}}}
-+}
-+
-+static void fe_tobytes(uint8_t s[32], const fe *f) {
-+  assert_fe(f->v);
-+  uint64_t h[5];
-+  fe_freeze(h, f->v);
-+  assert_fe_frozen(h);
-+
-+  s[0] = h[0] >> 0;
-+  s[1] = h[0] >> 8;
-+  s[2] = h[0] >> 16;
-+  s[3] = h[0] >> 24;
-+  s[4] = h[0] >> 32;
-+  s[5] = h[0] >> 40;
-+  s[6] = (h[0] >> 48) | (h[1] << 3);
-+  s[7] = h[1] >> 5;
-+  s[8] = h[1] >> 13;
-+  s[9] = h[1] >> 21;
-+  s[10] = h[1] >> 29;
-+  s[11] = h[1] >> 37;
-+  s[12] = (h[1] >> 45) | (h[2] << 6);
-+  s[13] = h[2] >> 2;
-+  s[14] = h[2] >> 10;
-+  s[15] = h[2] >> 18;
-+  s[16] = h[2] >> 26;
-+  s[17] = h[2] >> 34;
-+  s[18] = h[2] >> 42;
-+  s[19] = (h[2] >> 50) | (h[3] << 1);
-+  s[20] = h[3] >> 7;
-+  s[21] = h[3] >> 15;
-+  s[22] = h[3] >> 23;
-+  s[23] = h[3] >> 31;
-+  s[24] = h[3] >> 39;
-+  s[25] = (h[3] >> 47) | (h[4] << 4);
-+  s[26] = h[4] >> 4;
-+  s[27] = h[4] >> 12;
-+  s[28] = h[4] >> 20;
-+  s[29] = h[4] >> 28;
-+  s[30] = h[4] >> 36;
-+  s[31] = h[4] >> 44;
-+}
-+
-+// h = 0
-+static void fe_0(fe *h) {
-+  memset(h, 0, sizeof(fe));
-+}
-+
-+static void fe_loose_0(fe_loose *h) {
-+  memset(h, 0, sizeof(fe_loose));
-+}
-+
-+// h = 1
-+static void fe_1(fe *h) {
-+  memset(h, 0, sizeof(fe));
-+  h->v[0] = 1;
-+}
-+
-+static void fe_loose_1(fe_loose *h) {
-+  memset(h, 0, sizeof(fe_loose));
-+  h->v[0] = 1;
-+}
-+
-+static void fe_add_impl(uint64_t out[5], const uint64_t in1[5], const uint64_t in2[5]) {
-+  { const uint64_t x10 = in1[4];
-+  { const uint64_t x11 = in1[3];
-+  { const uint64_t x9 = in1[2];
-+  { const uint64_t x7 = in1[1];
-+  { const uint64_t x5 = in1[0];
-+  { const uint64_t x18 = in2[4];
-+  { const uint64_t x19 = in2[3];
-+  { const uint64_t x17 = in2[2];
-+  { const uint64_t x15 = in2[1];
-+  { const uint64_t x13 = in2[0];
-+  out[0] = (x5 + x13);
-+  out[1] = (x7 + x15);
-+  out[2] = (x9 + x17);
-+  out[3] = (x11 + x19);
-+  out[4] = (x10 + x18);
-+  }}}}}}}}}}
-+}
-+
-+// h = f + g
-+// Can overlap h with f or g.
-+static void fe_add(fe_loose *h, const fe *f, const fe *g) {
-+  assert_fe(f->v);
-+  assert_fe(g->v);
-+  fe_add_impl(h->v, f->v, g->v);
-+  assert_fe_loose(h->v);
-+}
-+
-+static void fe_sub_impl(uint64_t out[5], const uint64_t in1[5], const uint64_t in2[5]) {
-+  { const uint64_t x10 = in1[4];
-+  { const uint64_t x11 = in1[3];
-+  { const uint64_t x9 = in1[2];
-+  { const uint64_t x7 = in1[1];
-+  { const uint64_t x5 = in1[0];
-+  { const uint64_t x18 = in2[4];
-+  { const uint64_t x19 = in2[3];
-+  { const uint64_t x17 = in2[2];
-+  { const uint64_t x15 = in2[1];
-+  { const uint64_t x13 = in2[0];
-+  out[0] = ((0xfffffffffffda + x5) - x13);
-+  out[1] = ((0xffffffffffffe + x7) - x15);
-+  out[2] = ((0xffffffffffffe + x9) - x17);
-+  out[3] = ((0xffffffffffffe + x11) - x19);
-+  out[4] = ((0xffffffffffffe + x10) - x18);
-+  }}}}}}}}}}
-+}
-+
-+// h = f - g
-+// Can overlap h with f or g.
-+static void fe_sub(fe_loose *h, const fe *f, const fe *g) {
-+  assert_fe(f->v);
-+  assert_fe(g->v);
-+  fe_sub_impl(h->v, f->v, g->v);
-+  assert_fe_loose(h->v);
-+}
-+
-+static void fe_carry_impl(uint64_t out[5], const uint64_t in1[5]) {
-+  { const uint64_t x7 = in1[4];
-+  { const uint64_t x8 = in1[3];
-+  { const uint64_t x6 = in1[2];
-+  { const uint64_t x4 = in1[1];
-+  { const uint64_t x2 = in1[0];
-+  { uint64_t x9 = (x2 >> 0x33);
-+  { uint64_t x10 = (x2 & 0x7ffffffffffff);
-+  { uint64_t x11 = (x9 + x4);
-+  { uint64_t x12 = (x11 >> 0x33);
-+  { uint64_t x13 = (x11 & 0x7ffffffffffff);
-+  { uint64_t x14 = (x12 + x6);
-+  { uint64_t x15 = (x14 >> 0x33);
-+  { uint64_t x16 = (x14 & 0x7ffffffffffff);
-+  { uint64_t x17 = (x15 + x8);
-+  { uint64_t x18 = (x17 >> 0x33);
-+  { uint64_t x19 = (x17 & 0x7ffffffffffff);
-+  { uint64_t x20 = (x18 + x7);
-+  { uint64_t x21 = (x20 >> 0x33);
-+  { uint64_t x22 = (x20 & 0x7ffffffffffff);
-+  { uint64_t x23 = (x10 + (0x13 * x21));
-+  { uint64_t x24 = (x23 >> 0x33);
-+  { uint64_t x25 = (x23 & 0x7ffffffffffff);
-+  { uint64_t x26 = (x24 + x13);
-+  { uint64_t x27 = (x26 >> 0x33);
-+  { uint64_t x28 = (x26 & 0x7ffffffffffff);
-+  out[0] = x25;
-+  out[1] = x28;
-+  out[2] = (x27 + x16);
-+  out[3] = x19;
-+  out[4] = x22;
-+  }}}}}}}}}}}}}}}}}}}}}}}}}
-+}
-+
-+static void fe_carry(fe *h, const fe_loose* f) {
-+  assert_fe_loose(f->v);
-+  fe_carry_impl(h->v, f->v);
-+  assert_fe(h->v);
-+}
-+
-+static void fe_mul_impl(uint64_t out[5], const uint64_t in1[5], const uint64_t in2[5]) {
-+  assert_fe_loose(in1);
-+  assert_fe_loose(in2);
-+  { const uint64_t x10 = in1[4];
-+  { const uint64_t x11 = in1[3];
-+  { const uint64_t x9 = in1[2];
-+  { const uint64_t x7 = in1[1];
-+  { const uint64_t x5 = in1[0];
-+  { const uint64_t x18 = in2[4];
-+  { const uint64_t x19 = in2[3];
-+  { const uint64_t x17 = in2[2];
-+  { const uint64_t x15 = in2[1];
-+  { const uint64_t x13 = in2[0];
-+  { uint128_t x20 = ((uint128_t)x5 * x13);
-+  { uint128_t x21 = (((uint128_t)x5 * x15) + ((uint128_t)x7 * x13));
-+  { uint128_t x22 = ((((uint128_t)x5 * x17) + ((uint128_t)x9 * x13)) + ((uint128_t)x7 * x15));
-+  { uint128_t x23 = (((((uint128_t)x5 * x19) + ((uint128_t)x11 * x13)) + ((uint128_t)x7 * x17)) + ((uint128_t)x9 * x15));
-+  { uint128_t x24 = ((((((uint128_t)x5 * x18) + ((uint128_t)x10 * x13)) + ((uint128_t)x11 * x15)) + ((uint128_t)x7 * x19)) + ((uint128_t)x9 * x17));
-+  { uint64_t x25 = (x10 * 0x13);
-+  { uint64_t x26 = (x7 * 0x13);
-+  { uint64_t x27 = (x9 * 0x13);
-+  { uint64_t x28 = (x11 * 0x13);
-+  { uint128_t x29 = ((((x20 + ((uint128_t)x25 * x15)) + ((uint128_t)x26 * x18)) + ((uint128_t)x27 * x19)) + ((uint128_t)x28 * x17));
-+  { uint128_t x30 = (((x21 + ((uint128_t)x25 * x17)) + ((uint128_t)x27 * x18)) + ((uint128_t)x28 * x19));
-+  { uint128_t x31 = ((x22 + ((uint128_t)x25 * x19)) + ((uint128_t)x28 * x18));
-+  { uint128_t x32 = (x23 + ((uint128_t)x25 * x18));
-+  { uint64_t x33 = (uint64_t) (x29 >> 0x33);
-+  { uint64_t x34 = ((uint64_t)x29 & 0x7ffffffffffff);
-+  { uint128_t x35 = (x33 + x30);
-+  { uint64_t x36 = (uint64_t) (x35 >> 0x33);
-+  { uint64_t x37 = ((uint64_t)x35 & 0x7ffffffffffff);
-+  { uint128_t x38 = (x36 + x31);
-+  { uint64_t x39 = (uint64_t) (x38 >> 0x33);
-+  { uint64_t x40 = ((uint64_t)x38 & 0x7ffffffffffff);
-+  { uint128_t x41 = (x39 + x32);
-+  { uint64_t x42 = (uint64_t) (x41 >> 0x33);
-+  { uint64_t x43 = ((uint64_t)x41 & 0x7ffffffffffff);
-+  { uint128_t x44 = (x42 + x24);
-+  { uint64_t x45 = (uint64_t) (x44 >> 0x33);
-+  { uint64_t x46 = ((uint64_t)x44 & 0x7ffffffffffff);
-+  { uint64_t x47 = (x34 + (0x13 * x45));
-+  { uint64_t x48 = (x47 >> 0x33);
-+  { uint64_t x49 = (x47 & 0x7ffffffffffff);
-+  { uint64_t x50 = (x48 + x37);
-+  { uint64_t x51 = (x50 >> 0x33);
-+  { uint64_t x52 = (x50 & 0x7ffffffffffff);
-+  out[0] = x49;
-+  out[1] = x52;
-+  out[2] = (x51 + x40);
-+  out[3] = x43;
-+  out[4] = x46;
-+  }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
-+  assert_fe(out);
-+}
-+
-+static void fe_mul_ltt(fe_loose *h, const fe *f, const fe *g) {
-+  fe_mul_impl(h->v, f->v, g->v);
-+}
-+
-+static void fe_mul_llt(fe_loose *h, const fe_loose *f, const fe *g) {
-+  fe_mul_impl(h->v, f->v, g->v);
-+}
-+
-+static void fe_mul_ttt(fe *h, const fe *f, const fe *g) {
-+  fe_mul_impl(h->v, f->v, g->v);
-+}
-+
-+static void fe_mul_tlt(fe *h, const fe_loose *f, const fe *g) {
-+  fe_mul_impl(h->v, f->v, g->v);
-+}
-+
-+static void fe_mul_ttl(fe *h, const fe *f, const fe_loose *g) {
-+  fe_mul_impl(h->v, f->v, g->v);
-+}
-+
-+static void fe_mul_tll(fe *h, const fe_loose *f, const fe_loose *g) {
-+  fe_mul_impl(h->v, f->v, g->v);
-+}
-+
-+static void fe_sqr_impl(uint64_t out[5], const uint64_t in1[5]) {
-+  assert_fe_loose(in1);
-+  { const uint64_t x7 = in1[4];
-+  { const uint64_t x8 = in1[3];
-+  { const uint64_t x6 = in1[2];
-+  { const uint64_t x4 = in1[1];
-+  { const uint64_t x2 = in1[0];
-+  { uint64_t x9 = (x2 * 0x2);
-+  { uint64_t x10 = (x4 * 0x2);
-+  { uint64_t x11 = ((x6 * 0x2) * 0x13);
-+  { uint64_t x12 = (x7 * 0x13);
-+  { uint64_t x13 = (x12 * 0x2);
-+  { uint128_t x14 = ((((uint128_t)x2 * x2) + ((uint128_t)x13 * x4)) + ((uint128_t)x11 * x8));
-+  { uint128_t x15 = ((((uint128_t)x9 * x4) + ((uint128_t)x13 * x6)) + ((uint128_t)x8 * (x8 * 0x13)));
-+  { uint128_t x16 = ((((uint128_t)x9 * x6) + ((uint128_t)x4 * x4)) + ((uint128_t)x13 * x8));
-+  { uint128_t x17 = ((((uint128_t)x9 * x8) + ((uint128_t)x10 * x6)) + ((uint128_t)x7 * x12));
-+  { uint128_t x18 = ((((uint128_t)x9 * x7) + ((uint128_t)x10 * x8)) + ((uint128_t)x6 * x6));
-+  { uint64_t x19 = (uint64_t) (x14 >> 0x33);
-+  { uint64_t x20 = ((uint64_t)x14 & 0x7ffffffffffff);
-+  { uint128_t x21 = (x19 + x15);
-+  { uint64_t x22 = (uint64_t) (x21 >> 0x33);
-+  { uint64_t x23 = ((uint64_t)x21 & 0x7ffffffffffff);
-+  { uint128_t x24 = (x22 + x16);
-+  { uint64_t x25 = (uint64_t) (x24 >> 0x33);
-+  { uint64_t x26 = ((uint64_t)x24 & 0x7ffffffffffff);
-+  { uint128_t x27 = (x25 + x17);
-+  { uint64_t x28 = (uint64_t) (x27 >> 0x33);
-+  { uint64_t x29 = ((uint64_t)x27 & 0x7ffffffffffff);
-+  { uint128_t x30 = (x28 + x18);
-+  { uint64_t x31 = (uint64_t) (x30 >> 0x33);
-+  { uint64_t x32 = ((uint64_t)x30 & 0x7ffffffffffff);
-+  { uint64_t x33 = (x20 + (0x13 * x31));
-+  { uint64_t x34 = (x33 >> 0x33);
-+  { uint64_t x35 = (x33 & 0x7ffffffffffff);
-+  { uint64_t x36 = (x34 + x23);
-+  { uint64_t x37 = (x36 >> 0x33);
-+  { uint64_t x38 = (x36 & 0x7ffffffffffff);
-+  out[0] = x35;
-+  out[1] = x38;
-+  out[2] = (x37 + x26);
-+  out[3] = x29;
-+  out[4] = x32;
-+  }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
-+  assert_fe(out);
-+}
-+
-+static void fe_sq_tl(fe *h, const fe_loose *f) {
-+  fe_sqr_impl(h->v, f->v);
-+}
-+
-+static void fe_sq_tt(fe *h, const fe *f) {
-+  fe_sqr_impl(h->v, f->v);
-+}
-+
-+// Adapted from Fiat-synthesized |fe_sub_impl| with |out| = 0.
-+static void fe_neg_impl(uint64_t out[5], const uint64_t in2[5]) {
-+  { const uint64_t x10 = 0;
-+  { const uint64_t x11 = 0;
-+  { const uint64_t x9 = 0;
-+  { const uint64_t x7 = 0;
-+  { const uint64_t x5 = 0;
-+  { const uint64_t x18 = in2[4];
-+  { const uint64_t x19 = in2[3];
-+  { const uint64_t x17 = in2[2];
-+  { const uint64_t x15 = in2[1];
-+  { const uint64_t x13 = in2[0];
-+  out[0] = ((0xfffffffffffda + x5) - x13);
-+  out[1] = ((0xffffffffffffe + x7) - x15);
-+  out[2] = ((0xffffffffffffe + x9) - x17);
-+  out[3] = ((0xffffffffffffe + x11) - x19);
-+  out[4] = ((0xffffffffffffe + x10) - x18);
-+  }}}}}}}}}}
-+}
-+
-+// h = -f
-+static void fe_neg(fe_loose *h, const fe *f) {
-+  assert_fe(f->v);
-+  fe_neg_impl(h->v, f->v);
-+  assert_fe_loose(h->v);
-+}
-+
-+// Replace (f,g) with (g,g) if b == 1;
-+// replace (f,g) with (f,g) if b == 0.
-+//
-+// Preconditions: b in {0,1}.
-+static void fe_cmov(fe_loose *f, const fe_loose *g, uint64_t b) {
-+  unsigned i;
-+  b = 0-b;
-+  for (i = 0; i < 5; i++) {
-+    uint64_t x = f->v[i] ^ g->v[i];
-+    x &= b;
-+    f->v[i] ^= x;
-+  }
-+}
-+
-+#else
-+
-+#ifdef EDWARDS25519_ASSERTS
-+#define assert_fe(f) do { \
-+  unsigned _assert_fe_i; \
-+  for (_assert_fe_i = 0; _assert_fe_i< 10; _assert_fe_i++) { \
-+    assert(f[_assert_fe_i] < 1.125*(1<<(26-(_assert_fe_i&1)))); \
-+  } \
-+} while (0)
-+
-+#define assert_fe_loose(f) do { \
-+  unsigned _assert_fe_i; \
-+  for (_assert_fe_i = 0; _assert_fe_i< 10; _assert_fe_i++) { \
-+    assert(f[_assert_fe_i] < 3.375*(1<<(26-(_assert_fe_i&1)))); \
-+  } \
-+} while (0)
-+
-+#define assert_fe_frozen(f) do { \
-+  unsigned _assert_fe_i; \
-+  for (_assert_fe_i = 0; _assert_fe_i< 10; _assert_fe_i++) { \
-+    assert(f[_assert_fe_i] < (1u<<(26-(_assert_fe_i&1)))); \
-+  } \
-+} while (0)
-+#endif /* EDWARDS25519_ASSERTS */
-+
-+static void fe_frombytes_impl(uint32_t h[10], const uint8_t *s) {
-+  // Ignores top bit of s.
-+  uint32_t a0 = load_4(s);
-+  uint32_t a1 = load_4(s+4);
-+  uint32_t a2 = load_4(s+8);
-+  uint32_t a3 = load_4(s+12);
-+  uint32_t a4 = load_4(s+16);
-+  uint32_t a5 = load_4(s+20);
-+  uint32_t a6 = load_4(s+24);
-+  uint32_t a7 = load_4(s+28);
-+  h[0] = a0&((1<<26)-1);                    // 26 used, 32-26 left.   26
-+  h[1] = (a0>>26) | ((a1&((1<<19)-1))<< 6); // (32-26) + 19 =  6+19 = 25
-+  h[2] = (a1>>19) | ((a2&((1<<13)-1))<<13); // (32-19) + 13 = 13+13 = 26
-+  h[3] = (a2>>13) | ((a3&((1<< 6)-1))<<19); // (32-13) +  6 = 19+ 6 = 25
-+  h[4] = (a3>> 6);                          // (32- 6)              = 26
-+  h[5] = a4&((1<<25)-1);                    //                        25
-+  h[6] = (a4>>25) | ((a5&((1<<19)-1))<< 7); // (32-25) + 19 =  7+19 = 26
-+  h[7] = (a5>>19) | ((a6&((1<<12)-1))<<13); // (32-19) + 12 = 13+12 = 25
-+  h[8] = (a6>>12) | ((a7&((1<< 6)-1))<<20); // (32-12) +  6 = 20+ 6 = 26
-+  h[9] = (a7>> 6)&((1<<25)-1); //                                     25
-+  assert_fe(h);
-+}
-+
-+static void fe_frombytes(fe *h, const uint8_t *s) {
-+  fe_frombytes_impl(h->v, s);
-+}
-+
-+static void fe_freeze(uint32_t out[10], const uint32_t in1[10]) {
-+  { const uint32_t x17 = in1[9];
-+  { const uint32_t x18 = in1[8];
-+  { const uint32_t x16 = in1[7];
-+  { const uint32_t x14 = in1[6];
-+  { const uint32_t x12 = in1[5];
-+  { const uint32_t x10 = in1[4];
-+  { const uint32_t x8 = in1[3];
-+  { const uint32_t x6 = in1[2];
-+  { const uint32_t x4 = in1[1];
-+  { const uint32_t x2 = in1[0];
-+  { uint32_t x20; uint8_t/*bool*/ x21 = subborrow_u26(0x0, x2, 0x3ffffed, &x20);
-+  { uint32_t x23; uint8_t/*bool*/ x24 = subborrow_u25(x21, x4, 0x1ffffff, &x23);
-+  { uint32_t x26; uint8_t/*bool*/ x27 = subborrow_u26(x24, x6, 0x3ffffff, &x26);
-+  { uint32_t x29; uint8_t/*bool*/ x30 = subborrow_u25(x27, x8, 0x1ffffff, &x29);
-+  { uint32_t x32; uint8_t/*bool*/ x33 = subborrow_u26(x30, x10, 0x3ffffff, &x32);
-+  { uint32_t x35; uint8_t/*bool*/ x36 = subborrow_u25(x33, x12, 0x1ffffff, &x35);
-+  { uint32_t x38; uint8_t/*bool*/ x39 = subborrow_u26(x36, x14, 0x3ffffff, &x38);
-+  { uint32_t x41; uint8_t/*bool*/ x42 = subborrow_u25(x39, x16, 0x1ffffff, &x41);
-+  { uint32_t x44; uint8_t/*bool*/ x45 = subborrow_u26(x42, x18, 0x3ffffff, &x44);
-+  { uint32_t x47; uint8_t/*bool*/ x48 = subborrow_u25(x45, x17, 0x1ffffff, &x47);
-+  { uint32_t x49 = cmovznz32(x48, 0x0, 0xffffffff);
-+  { uint32_t x50 = (x49 & 0x3ffffed);
-+  { uint32_t x52; uint8_t/*bool*/ x53 = addcarryx_u26(0x0, x20, x50, &x52);
-+  { uint32_t x54 = (x49 & 0x1ffffff);
-+  { uint32_t x56; uint8_t/*bool*/ x57 = addcarryx_u25(x53, x23, x54, &x56);
-+  { uint32_t x58 = (x49 & 0x3ffffff);
-+  { uint32_t x60; uint8_t/*bool*/ x61 = addcarryx_u26(x57, x26, x58, &x60);
-+  { uint32_t x62 = (x49 & 0x1ffffff);
-+  { uint32_t x64; uint8_t/*bool*/ x65 = addcarryx_u25(x61, x29, x62, &x64);
-+  { uint32_t x66 = (x49 & 0x3ffffff);
-+  { uint32_t x68; uint8_t/*bool*/ x69 = addcarryx_u26(x65, x32, x66, &x68);
-+  { uint32_t x70 = (x49 & 0x1ffffff);
-+  { uint32_t x72; uint8_t/*bool*/ x73 = addcarryx_u25(x69, x35, x70, &x72);
-+  { uint32_t x74 = (x49 & 0x3ffffff);
-+  { uint32_t x76; uint8_t/*bool*/ x77 = addcarryx_u26(x73, x38, x74, &x76);
-+  { uint32_t x78 = (x49 & 0x1ffffff);
-+  { uint32_t x80; uint8_t/*bool*/ x81 = addcarryx_u25(x77, x41, x78, &x80);
-+  { uint32_t x82 = (x49 & 0x3ffffff);
-+  { uint32_t x84; uint8_t/*bool*/ x85 = addcarryx_u26(x81, x44, x82, &x84);
-+  { uint32_t x86 = (x49 & 0x1ffffff);
-+  { uint32_t x88; addcarryx_u25(x85, x47, x86, &x88);
-+  out[0] = x52;
-+  out[1] = x56;
-+  out[2] = x60;
-+  out[3] = x64;
-+  out[4] = x68;
-+  out[5] = x72;
-+  out[6] = x76;
-+  out[7] = x80;
-+  out[8] = x84;
-+  out[9] = x88;
-+  }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
-+}
-+
-+static void fe_tobytes(uint8_t s[32], const fe *f) {
-+  assert_fe(f->v);
-+  uint32_t h[10];
-+  fe_freeze(h, f->v);
-+  assert_fe_frozen(h);
-+
-+  s[0] = h[0] >> 0;
-+  s[1] = h[0] >> 8;
-+  s[2] = h[0] >> 16;
-+  s[3] = (h[0] >> 24) | (h[1] << 2);
-+  s[4] = h[1] >> 6;
-+  s[5] = h[1] >> 14;
-+  s[6] = (h[1] >> 22) | (h[2] << 3);
-+  s[7] = h[2] >> 5;
-+  s[8] = h[2] >> 13;
-+  s[9] = (h[2] >> 21) | (h[3] << 5);
-+  s[10] = h[3] >> 3;
-+  s[11] = h[3] >> 11;
-+  s[12] = (h[3] >> 19) | (h[4] << 6);
-+  s[13] = h[4] >> 2;
-+  s[14] = h[4] >> 10;
-+  s[15] = h[4] >> 18;
-+  s[16] = h[5] >> 0;
-+  s[17] = h[5] >> 8;
-+  s[18] = h[5] >> 16;
-+  s[19] = (h[5] >> 24) | (h[6] << 1);
-+  s[20] = h[6] >> 7;
-+  s[21] = h[6] >> 15;
-+  s[22] = (h[6] >> 23) | (h[7] << 3);
-+  s[23] = h[7] >> 5;
-+  s[24] = h[7] >> 13;
-+  s[25] = (h[7] >> 21) | (h[8] << 4);
-+  s[26] = h[8] >> 4;
-+  s[27] = h[8] >> 12;
-+  s[28] = (h[8] >> 20) | (h[9] << 6);
-+  s[29] = h[9] >> 2;
-+  s[30] = h[9] >> 10;
-+  s[31] = h[9] >> 18;
-+}
-+
-+// h = 0
-+static void fe_0(fe *h) {
-+  memset(h, 0, sizeof(fe));
-+}
-+
-+static void fe_loose_0(fe_loose *h) {
-+  memset(h, 0, sizeof(fe_loose));
-+}
-+
-+// h = 1
-+static void fe_1(fe *h) {
-+  memset(h, 0, sizeof(fe));
-+  h->v[0] = 1;
-+}
-+
-+static void fe_loose_1(fe_loose *h) {
-+  memset(h, 0, sizeof(fe_loose));
-+  h->v[0] = 1;
-+}
-+
-+static void fe_add_impl(uint32_t out[10], const uint32_t in1[10], const uint32_t in2[10]) {
-+  { const uint32_t x20 = in1[9];
-+  { const uint32_t x21 = in1[8];
-+  { const uint32_t x19 = in1[7];
-+  { const uint32_t x17 = in1[6];
-+  { const uint32_t x15 = in1[5];
-+  { const uint32_t x13 = in1[4];
-+  { const uint32_t x11 = in1[3];
-+  { const uint32_t x9 = in1[2];
-+  { const uint32_t x7 = in1[1];
-+  { const uint32_t x5 = in1[0];
-+  { const uint32_t x38 = in2[9];
-+  { const uint32_t x39 = in2[8];
-+  { const uint32_t x37 = in2[7];
-+  { const uint32_t x35 = in2[6];
-+  { const uint32_t x33 = in2[5];
-+  { const uint32_t x31 = in2[4];
-+  { const uint32_t x29 = in2[3];
-+  { const uint32_t x27 = in2[2];
-+  { const uint32_t x25 = in2[1];
-+  { const uint32_t x23 = in2[0];
-+  out[0] = (x5 + x23);
-+  out[1] = (x7 + x25);
-+  out[2] = (x9 + x27);
-+  out[3] = (x11 + x29);
-+  out[4] = (x13 + x31);
-+  out[5] = (x15 + x33);
-+  out[6] = (x17 + x35);
-+  out[7] = (x19 + x37);
-+  out[8] = (x21 + x39);
-+  out[9] = (x20 + x38);
-+  }}}}}}}}}}}}}}}}}}}}
-+}
-+
-+// h = f + g
-+// Can overlap h with f or g.
-+static void fe_add(fe_loose *h, const fe *f, const fe *g) {
-+  assert_fe(f->v);
-+  assert_fe(g->v);
-+  fe_add_impl(h->v, f->v, g->v);
-+  assert_fe_loose(h->v);
-+}
-+
-+static void fe_sub_impl(uint32_t out[10], const uint32_t in1[10], const uint32_t in2[10]) {
-+  { const uint32_t x20 = in1[9];
-+  { const uint32_t x21 = in1[8];
-+  { const uint32_t x19 = in1[7];
-+  { const uint32_t x17 = in1[6];
-+  { const uint32_t x15 = in1[5];
-+  { const uint32_t x13 = in1[4];
-+  { const uint32_t x11 = in1[3];
-+  { const uint32_t x9 = in1[2];
-+  { const uint32_t x7 = in1[1];
-+  { const uint32_t x5 = in1[0];
-+  { const uint32_t x38 = in2[9];
-+  { const uint32_t x39 = in2[8];
-+  { const uint32_t x37 = in2[7];
-+  { const uint32_t x35 = in2[6];
-+  { const uint32_t x33 = in2[5];
-+  { const uint32_t x31 = in2[4];
-+  { const uint32_t x29 = in2[3];
-+  { const uint32_t x27 = in2[2];
-+  { const uint32_t x25 = in2[1];
-+  { const uint32_t x23 = in2[0];
-+  out[0] = ((0x7ffffda + x5) - x23);
-+  out[1] = ((0x3fffffe + x7) - x25);
-+  out[2] = ((0x7fffffe + x9) - x27);
-+  out[3] = ((0x3fffffe + x11) - x29);
-+  out[4] = ((0x7fffffe + x13) - x31);
-+  out[5] = ((0x3fffffe + x15) - x33);
-+  out[6] = ((0x7fffffe + x17) - x35);
-+  out[7] = ((0x3fffffe + x19) - x37);
-+  out[8] = ((0x7fffffe + x21) - x39);
-+  out[9] = ((0x3fffffe + x20) - x38);
-+  }}}}}}}}}}}}}}}}}}}}
-+}
-+
-+// h = f - g
-+// Can overlap h with f or g.
-+static void fe_sub(fe_loose *h, const fe *f, const fe *g) {
-+  assert_fe(f->v);
-+  assert_fe(g->v);
-+  fe_sub_impl(h->v, f->v, g->v);
-+  assert_fe_loose(h->v);
-+}
-+
-+static void fe_carry_impl(uint32_t out[10], const uint32_t in1[10]) {
-+  { const uint32_t x17 = in1[9];
-+  { const uint32_t x18 = in1[8];
-+  { const uint32_t x16 = in1[7];
-+  { const uint32_t x14 = in1[6];
-+  { const uint32_t x12 = in1[5];
-+  { const uint32_t x10 = in1[4];
-+  { const uint32_t x8 = in1[3];
-+  { const uint32_t x6 = in1[2];
-+  { const uint32_t x4 = in1[1];
-+  { const uint32_t x2 = in1[0];
-+  { uint32_t x19 = (x2 >> 0x1a);
-+  { uint32_t x20 = (x2 & 0x3ffffff);
-+  { uint32_t x21 = (x19 + x4);
-+  { uint32_t x22 = (x21 >> 0x19);
-+  { uint32_t x23 = (x21 & 0x1ffffff);
-+  { uint32_t x24 = (x22 + x6);
-+  { uint32_t x25 = (x24 >> 0x1a);
-+  { uint32_t x26 = (x24 & 0x3ffffff);
-+  { uint32_t x27 = (x25 + x8);
-+  { uint32_t x28 = (x27 >> 0x19);
-+  { uint32_t x29 = (x27 & 0x1ffffff);
-+  { uint32_t x30 = (x28 + x10);
-+  { uint32_t x31 = (x30 >> 0x1a);
-+  { uint32_t x32 = (x30 & 0x3ffffff);
-+  { uint32_t x33 = (x31 + x12);
-+  { uint32_t x34 = (x33 >> 0x19);
-+  { uint32_t x35 = (x33 & 0x1ffffff);
-+  { uint32_t x36 = (x34 + x14);
-+  { uint32_t x37 = (x36 >> 0x1a);
-+  { uint32_t x38 = (x36 & 0x3ffffff);
-+  { uint32_t x39 = (x37 + x16);
-+  { uint32_t x40 = (x39 >> 0x19);
-+  { uint32_t x41 = (x39 & 0x1ffffff);
-+  { uint32_t x42 = (x40 + x18);
-+  { uint32_t x43 = (x42 >> 0x1a);
-+  { uint32_t x44 = (x42 & 0x3ffffff);
-+  { uint32_t x45 = (x43 + x17);
-+  { uint32_t x46 = (x45 >> 0x19);
-+  { uint32_t x47 = (x45 & 0x1ffffff);
-+  { uint32_t x48 = (x20 + (0x13 * x46));
-+  { uint32_t x49 = (x48 >> 0x1a);
-+  { uint32_t x50 = (x48 & 0x3ffffff);
-+  { uint32_t x51 = (x49 + x23);
-+  { uint32_t x52 = (x51 >> 0x19);
-+  { uint32_t x53 = (x51 & 0x1ffffff);
-+  out[0] = x50;
-+  out[1] = x53;
-+  out[2] = (x52 + x26);
-+  out[3] = x29;
-+  out[4] = x32;
-+  out[5] = x35;
-+  out[6] = x38;
-+  out[7] = x41;
-+  out[8] = x44;
-+  out[9] = x47;
-+  }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
-+}
-+
-+static void fe_carry(fe *h, const fe_loose* f) {
-+  assert_fe_loose(f->v);
-+  fe_carry_impl(h->v, f->v);
-+  assert_fe(h->v);
-+}
-+
-+static void fe_mul_impl(uint32_t out[10], const uint32_t in1[10], const uint32_t in2[10]) {
-+  assert_fe_loose(in1);
-+  assert_fe_loose(in2);
-+  { const uint32_t x20 = in1[9];
-+  { const uint32_t x21 = in1[8];
-+  { const uint32_t x19 = in1[7];
-+  { const uint32_t x17 = in1[6];
-+  { const uint32_t x15 = in1[5];
-+  { const uint32_t x13 = in1[4];
-+  { const uint32_t x11 = in1[3];
-+  { const uint32_t x9 = in1[2];
-+  { const uint32_t x7 = in1[1];
-+  { const uint32_t x5 = in1[0];
-+  { const uint32_t x38 = in2[9];
-+  { const uint32_t x39 = in2[8];
-+  { const uint32_t x37 = in2[7];
-+  { const uint32_t x35 = in2[6];
-+  { const uint32_t x33 = in2[5];
-+  { const uint32_t x31 = in2[4];
-+  { const uint32_t x29 = in2[3];
-+  { const uint32_t x27 = in2[2];
-+  { const uint32_t x25 = in2[1];
-+  { const uint32_t x23 = in2[0];
-+  { uint64_t x40 = ((uint64_t)x23 * x5);
-+  { uint64_t x41 = (((uint64_t)x23 * x7) + ((uint64_t)x25 * x5));
-+  { uint64_t x42 = ((((uint64_t)(0x2 * x25) * x7) + ((uint64_t)x23 * x9)) + ((uint64_t)x27 * x5));
-+  { uint64_t x43 = (((((uint64_t)x25 * x9) + ((uint64_t)x27 * x7)) + ((uint64_t)x23 * x11)) + ((uint64_t)x29 * x5));
-+  { uint64_t x44 = (((((uint64_t)x27 * x9) + (0x2 * (((uint64_t)x25 * x11) + ((uint64_t)x29 * x7)))) + ((uint64_t)x23 * x13)) + ((uint64_t)x31 * x5));
-+  { uint64_t x45 = (((((((uint64_t)x27 * x11) + ((uint64_t)x29 * x9)) + ((uint64_t)x25 * x13)) + ((uint64_t)x31 * x7)) + ((uint64_t)x23 * x15)) + ((uint64_t)x33 * x5));
-+  { uint64_t x46 = (((((0x2 * ((((uint64_t)x29 * x11) + ((uint64_t)x25 * x15)) + ((uint64_t)x33 * x7))) + ((uint64_t)x27 * x13)) + ((uint64_t)x31 * x9)) + ((uint64_t)x23 * x17)) + ((uint64_t)x35 * x5));
-+  { uint64_t x47 = (((((((((uint64_t)x29 * x13) + ((uint64_t)x31 * x11)) + ((uint64_t)x27 * x15)) + ((uint64_t)x33 * x9)) + ((uint64_t)x25 * x17)) + ((uint64_t)x35 * x7)) + ((uint64_t)x23 * x19)) + ((uint64_t)x37 * x5));
-+  { uint64_t x48 = (((((((uint64_t)x31 * x13) + (0x2 * (((((uint64_t)x29 * x15) + ((uint64_t)x33 * x11)) + ((uint64_t)x25 * x19)) + ((uint64_t)x37 * x7)))) + ((uint64_t)x27 * x17)) + ((uint64_t)x35 * x9)) + ((uint64_t)x23 * x21)) + ((uint64_t)x39 * x5));
-+  { uint64_t x49 = (((((((((((uint64_t)x31 * x15) + ((uint64_t)x33 * x13)) + ((uint64_t)x29 * x17)) + ((uint64_t)x35 * x11)) + ((uint64_t)x27 * x19)) + ((uint64_t)x37 * x9)) + ((uint64_t)x25 * x21)) + ((uint64_t)x39 * x7)) + ((uint64_t)x23 * x20)) + ((uint64_t)x38 * x5));
-+  { uint64_t x50 = (((((0x2 * ((((((uint64_t)x33 * x15) + ((uint64_t)x29 * x19)) + ((uint64_t)x37 * x11)) + ((uint64_t)x25 * x20)) + ((uint64_t)x38 * x7))) + ((uint64_t)x31 * x17)) + ((uint64_t)x35 * x13)) + ((uint64_t)x27 * x21)) + ((uint64_t)x39 * x9));
-+  { uint64_t x51 = (((((((((uint64_t)x33 * x17) + ((uint64_t)x35 * x15)) + ((uint64_t)x31 * x19)) + ((uint64_t)x37 * x13)) + ((uint64_t)x29 * x21)) + ((uint64_t)x39 * x11)) + ((uint64_t)x27 * x20)) + ((uint64_t)x38 * x9));
-+  { uint64_t x52 = (((((uint64_t)x35 * x17) + (0x2 * (((((uint64_t)x33 * x19) + ((uint64_t)x37 * x15)) + ((uint64_t)x29 * x20)) + ((uint64_t)x38 * x11)))) + ((uint64_t)x31 * x21)) + ((uint64_t)x39 * x13));
-+  { uint64_t x53 = (((((((uint64_t)x35 * x19) + ((uint64_t)x37 * x17)) + ((uint64_t)x33 * x21)) + ((uint64_t)x39 * x15)) + ((uint64_t)x31 * x20)) + ((uint64_t)x38 * x13));
-+  { uint64_t x54 = (((0x2 * ((((uint64_t)x37 * x19) + ((uint64_t)x33 * x20)) + ((uint64_t)x38 * x15))) + ((uint64_t)x35 * x21)) + ((uint64_t)x39 * x17));
-+  { uint64_t x55 = (((((uint64_t)x37 * x21) + ((uint64_t)x39 * x19)) + ((uint64_t)x35 * x20)) + ((uint64_t)x38 * x17));
-+  { uint64_t x56 = (((uint64_t)x39 * x21) + (0x2 * (((uint64_t)x37 * x20) + ((uint64_t)x38 * x19))));
-+  { uint64_t x57 = (((uint64_t)x39 * x20) + ((uint64_t)x38 * x21));
-+  { uint64_t x58 = ((uint64_t)(0x2 * x38) * x20);
-+  { uint64_t x59 = (x48 + (x58 << 0x4));
-+  { uint64_t x60 = (x59 + (x58 << 0x1));
-+  { uint64_t x61 = (x60 + x58);
-+  { uint64_t x62 = (x47 + (x57 << 0x4));
-+  { uint64_t x63 = (x62 + (x57 << 0x1));
-+  { uint64_t x64 = (x63 + x57);
-+  { uint64_t x65 = (x46 + (x56 << 0x4));
-+  { uint64_t x66 = (x65 + (x56 << 0x1));
-+  { uint64_t x67 = (x66 + x56);
-+  { uint64_t x68 = (x45 + (x55 << 0x4));
-+  { uint64_t x69 = (x68 + (x55 << 0x1));
-+  { uint64_t x70 = (x69 + x55);
-+  { uint64_t x71 = (x44 + (x54 << 0x4));
-+  { uint64_t x72 = (x71 + (x54 << 0x1));
-+  { uint64_t x73 = (x72 + x54);
-+  { uint64_t x74 = (x43 + (x53 << 0x4));
-+  { uint64_t x75 = (x74 + (x53 << 0x1));
-+  { uint64_t x76 = (x75 + x53);
-+  { uint64_t x77 = (x42 + (x52 << 0x4));
-+  { uint64_t x78 = (x77 + (x52 << 0x1));
-+  { uint64_t x79 = (x78 + x52);
-+  { uint64_t x80 = (x41 + (x51 << 0x4));
-+  { uint64_t x81 = (x80 + (x51 << 0x1));
-+  { uint64_t x82 = (x81 + x51);
-+  { uint64_t x83 = (x40 + (x50 << 0x4));
-+  { uint64_t x84 = (x83 + (x50 << 0x1));
-+  { uint64_t x85 = (x84 + x50);
-+  { uint64_t x86 = (x85 >> 0x1a);
-+  { uint32_t x87 = ((uint32_t)x85 & 0x3ffffff);
-+  { uint64_t x88 = (x86 + x82);
-+  { uint64_t x89 = (x88 >> 0x19);
-+  { uint32_t x90 = ((uint32_t)x88 & 0x1ffffff);
-+  { uint64_t x91 = (x89 + x79);
-+  { uint64_t x92 = (x91 >> 0x1a);
-+  { uint32_t x93 = ((uint32_t)x91 & 0x3ffffff);
-+  { uint64_t x94 = (x92 + x76);
-+  { uint64_t x95 = (x94 >> 0x19);
-+  { uint32_t x96 = ((uint32_t)x94 & 0x1ffffff);
-+  { uint64_t x97 = (x95 + x73);
-+  { uint64_t x98 = (x97 >> 0x1a);
-+  { uint32_t x99 = ((uint32_t)x97 & 0x3ffffff);
-+  { uint64_t x100 = (x98 + x70);
-+  { uint64_t x101 = (x100 >> 0x19);
-+  { uint32_t x102 = ((uint32_t)x100 & 0x1ffffff);
-+  { uint64_t x103 = (x101 + x67);
-+  { uint64_t x104 = (x103 >> 0x1a);
-+  { uint32_t x105 = ((uint32_t)x103 & 0x3ffffff);
-+  { uint64_t x106 = (x104 + x64);
-+  { uint64_t x107 = (x106 >> 0x19);
-+  { uint32_t x108 = ((uint32_t)x106 & 0x1ffffff);
-+  { uint64_t x109 = (x107 + x61);
-+  { uint64_t x110 = (x109 >> 0x1a);
-+  { uint32_t x111 = ((uint32_t)x109 & 0x3ffffff);
-+  { uint64_t x112 = (x110 + x49);
-+  { uint64_t x113 = (x112 >> 0x19);
-+  { uint32_t x114 = ((uint32_t)x112 & 0x1ffffff);
-+  { uint64_t x115 = (x87 + (0x13 * x113));
-+  { uint32_t x116 = (uint32_t) (x115 >> 0x1a);
-+  { uint32_t x117 = ((uint32_t)x115 & 0x3ffffff);
-+  { uint32_t x118 = (x116 + x90);
-+  { uint32_t x119 = (x118 >> 0x19);
-+  { uint32_t x120 = (x118 & 0x1ffffff);
-+  out[0] = x117;
-+  out[1] = x120;
-+  out[2] = (x119 + x93);
-+  out[3] = x96;
-+  out[4] = x99;
-+  out[5] = x102;
-+  out[6] = x105;
-+  out[7] = x108;
-+  out[8] = x111;
-+  out[9] = x114;
-+  }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
-+  assert_fe(out);
-+}
-+
-+static void fe_mul_ltt(fe_loose *h, const fe *f, const fe *g) {
-+  fe_mul_impl(h->v, f->v, g->v);
-+}
-+
-+static void fe_mul_llt(fe_loose *h, const fe_loose *f, const fe *g) {
-+  fe_mul_impl(h->v, f->v, g->v);
-+}
-+
-+static void fe_mul_ttt(fe *h, const fe *f, const fe *g) {
-+  fe_mul_impl(h->v, f->v, g->v);
-+}
-+
-+static void fe_mul_tlt(fe *h, const fe_loose *f, const fe *g) {
-+  fe_mul_impl(h->v, f->v, g->v);
-+}
-+
-+static void fe_mul_ttl(fe *h, const fe *f, const fe_loose *g) {
-+  fe_mul_impl(h->v, f->v, g->v);
-+}
-+
-+static void fe_mul_tll(fe *h, const fe_loose *f, const fe_loose *g) {
-+  fe_mul_impl(h->v, f->v, g->v);
-+}
-+
-+static void fe_sqr_impl(uint32_t out[10], const uint32_t in1[10]) {
-+  assert_fe_loose(in1);
-+  { const uint32_t x17 = in1[9];
-+  { const uint32_t x18 = in1[8];
-+  { const uint32_t x16 = in1[7];
-+  { const uint32_t x14 = in1[6];
-+  { const uint32_t x12 = in1[5];
-+  { const uint32_t x10 = in1[4];
-+  { const uint32_t x8 = in1[3];
-+  { const uint32_t x6 = in1[2];
-+  { const uint32_t x4 = in1[1];
-+  { const uint32_t x2 = in1[0];
-+  { uint64_t x19 = ((uint64_t)x2 * x2);
-+  { uint64_t x20 = ((uint64_t)(0x2 * x2) * x4);
-+  { uint64_t x21 = (0x2 * (((uint64_t)x4 * x4) + ((uint64_t)x2 * x6)));
-+  { uint64_t x22 = (0x2 * (((uint64_t)x4 * x6) + ((uint64_t)x2 * x8)));
-+  { uint64_t x23 = ((((uint64_t)x6 * x6) + ((uint64_t)(0x4 * x4) * x8)) + ((uint64_t)(0x2 * x2) * x10));
-+  { uint64_t x24 = (0x2 * ((((uint64_t)x6 * x8) + ((uint64_t)x4 * x10)) + ((uint64_t)x2 * x12)));
-+  { uint64_t x25 = (0x2 * (((((uint64_t)x8 * x8) + ((uint64_t)x6 * x10)) + ((uint64_t)x2 * x14)) + ((uint64_t)(0x2 * x4) * x12)));
-+  { uint64_t x26 = (0x2 * (((((uint64_t)x8 * x10) + ((uint64_t)x6 * x12)) + ((uint64_t)x4 * x14)) + ((uint64_t)x2 * x16)));
-+  { uint64_t x27 = (((uint64_t)x10 * x10) + (0x2 * ((((uint64_t)x6 * x14) + ((uint64_t)x2 * x18)) + (0x2 * (((uint64_t)x4 * x16) + ((uint64_t)x8 * x12))))));
-+  { uint64_t x28 = (0x2 * ((((((uint64_t)x10 * x12) + ((uint64_t)x8 * x14)) + ((uint64_t)x6 * x16)) + ((uint64_t)x4 * x18)) + ((uint64_t)x2 * x17)));
-+  { uint64_t x29 = (0x2 * (((((uint64_t)x12 * x12) + ((uint64_t)x10 * x14)) + ((uint64_t)x6 * x18)) + (0x2 * (((uint64_t)x8 * x16) + ((uint64_t)x4 * x17)))));
-+  { uint64_t x30 = (0x2 * (((((uint64_t)x12 * x14) + ((uint64_t)x10 * x16)) + ((uint64_t)x8 * x18)) + ((uint64_t)x6 * x17)));
-+  { uint64_t x31 = (((uint64_t)x14 * x14) + (0x2 * (((uint64_t)x10 * x18) + (0x2 * (((uint64_t)x12 * x16) + ((uint64_t)x8 * x17))))));
-+  { uint64_t x32 = (0x2 * ((((uint64_t)x14 * x16) + ((uint64_t)x12 * x18)) + ((uint64_t)x10 * x17)));
-+  { uint64_t x33 = (0x2 * ((((uint64_t)x16 * x16) + ((uint64_t)x14 * x18)) + ((uint64_t)(0x2 * x12) * x17)));
-+  { uint64_t x34 = (0x2 * (((uint64_t)x16 * x18) + ((uint64_t)x14 * x17)));
-+  { uint64_t x35 = (((uint64_t)x18 * x18) + ((uint64_t)(0x4 * x16) * x17));
-+  { uint64_t x36 = ((uint64_t)(0x2 * x18) * x17);
-+  { uint64_t x37 = ((uint64_t)(0x2 * x17) * x17);
-+  { uint64_t x38 = (x27 + (x37 << 0x4));
-+  { uint64_t x39 = (x38 + (x37 << 0x1));
-+  { uint64_t x40 = (x39 + x37);
-+  { uint64_t x41 = (x26 + (x36 << 0x4));
-+  { uint64_t x42 = (x41 + (x36 << 0x1));
-+  { uint64_t x43 = (x42 + x36);
-+  { uint64_t x44 = (x25 + (x35 << 0x4));
-+  { uint64_t x45 = (x44 + (x35 << 0x1));
-+  { uint64_t x46 = (x45 + x35);
-+  { uint64_t x47 = (x24 + (x34 << 0x4));
-+  { uint64_t x48 = (x47 + (x34 << 0x1));
-+  { uint64_t x49 = (x48 + x34);
-+  { uint64_t x50 = (x23 + (x33 << 0x4));
-+  { uint64_t x51 = (x50 + (x33 << 0x1));
-+  { uint64_t x52 = (x51 + x33);
-+  { uint64_t x53 = (x22 + (x32 << 0x4));
-+  { uint64_t x54 = (x53 + (x32 << 0x1));
-+  { uint64_t x55 = (x54 + x32);
-+  { uint64_t x56 = (x21 + (x31 << 0x4));
-+  { uint64_t x57 = (x56 + (x31 << 0x1));
-+  { uint64_t x58 = (x57 + x31);
-+  { uint64_t x59 = (x20 + (x30 << 0x4));
-+  { uint64_t x60 = (x59 + (x30 << 0x1));
-+  { uint64_t x61 = (x60 + x30);
-+  { uint64_t x62 = (x19 + (x29 << 0x4));
-+  { uint64_t x63 = (x62 + (x29 << 0x1));
-+  { uint64_t x64 = (x63 + x29);
-+  { uint64_t x65 = (x64 >> 0x1a);
-+  { uint32_t x66 = ((uint32_t)x64 & 0x3ffffff);
-+  { uint64_t x67 = (x65 + x61);
-+  { uint64_t x68 = (x67 >> 0x19);
-+  { uint32_t x69 = ((uint32_t)x67 & 0x1ffffff);
-+  { uint64_t x70 = (x68 + x58);
-+  { uint64_t x71 = (x70 >> 0x1a);
-+  { uint32_t x72 = ((uint32_t)x70 & 0x3ffffff);
-+  { uint64_t x73 = (x71 + x55);
-+  { uint64_t x74 = (x73 >> 0x19);
-+  { uint32_t x75 = ((uint32_t)x73 & 0x1ffffff);
-+  { uint64_t x76 = (x74 + x52);
-+  { uint64_t x77 = (x76 >> 0x1a);
-+  { uint32_t x78 = ((uint32_t)x76 & 0x3ffffff);
-+  { uint64_t x79 = (x77 + x49);
-+  { uint64_t x80 = (x79 >> 0x19);
-+  { uint32_t x81 = ((uint32_t)x79 & 0x1ffffff);
-+  { uint64_t x82 = (x80 + x46);
-+  { uint64_t x83 = (x82 >> 0x1a);
-+  { uint32_t x84 = ((uint32_t)x82 & 0x3ffffff);
-+  { uint64_t x85 = (x83 + x43);
-+  { uint64_t x86 = (x85 >> 0x19);
-+  { uint32_t x87 = ((uint32_t)x85 & 0x1ffffff);
-+  { uint64_t x88 = (x86 + x40);
-+  { uint64_t x89 = (x88 >> 0x1a);
-+  { uint32_t x90 = ((uint32_t)x88 & 0x3ffffff);
-+  { uint64_t x91 = (x89 + x28);
-+  { uint64_t x92 = (x91 >> 0x19);
-+  { uint32_t x93 = ((uint32_t)x91 & 0x1ffffff);
-+  { uint64_t x94 = (x66 + (0x13 * x92));
-+  { uint32_t x95 = (uint32_t) (x94 >> 0x1a);
-+  { uint32_t x96 = ((uint32_t)x94 & 0x3ffffff);
-+  { uint32_t x97 = (x95 + x69);
-+  { uint32_t x98 = (x97 >> 0x19);
-+  { uint32_t x99 = (x97 & 0x1ffffff);
-+  out[0] = x96;
-+  out[1] = x99;
-+  out[2] = (x98 + x72);
-+  out[3] = x75;
-+  out[4] = x78;
-+  out[5] = x81;
-+  out[6] = x84;
-+  out[7] = x87;
-+  out[8] = x90;
-+  out[9] = x93;
-+  }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
-+  assert_fe(out);
-+}
-+
-+static void fe_sq_tl(fe *h, const fe_loose *f) {
-+  fe_sqr_impl(h->v, f->v);
-+}
-+
-+static void fe_sq_tt(fe *h, const fe *f) {
-+  fe_sqr_impl(h->v, f->v);
-+}
-+
-+// Adapted from Fiat-synthesized |fe_sub_impl| with |out| = 0.
-+static void fe_neg_impl(uint32_t out[10], const uint32_t in2[10]) {
-+  { const uint32_t x20 = 0;
-+  { const uint32_t x21 = 0;
-+  { const uint32_t x19 = 0;
-+  { const uint32_t x17 = 0;
-+  { const uint32_t x15 = 0;
-+  { const uint32_t x13 = 0;
-+  { const uint32_t x11 = 0;
-+  { const uint32_t x9 = 0;
-+  { const uint32_t x7 = 0;
-+  { const uint32_t x5 = 0;
-+  { const uint32_t x38 = in2[9];
-+  { const uint32_t x39 = in2[8];
-+  { const uint32_t x37 = in2[7];
-+  { const uint32_t x35 = in2[6];
-+  { const uint32_t x33 = in2[5];
-+  { const uint32_t x31 = in2[4];
-+  { const uint32_t x29 = in2[3];
-+  { const uint32_t x27 = in2[2];
-+  { const uint32_t x25 = in2[1];
-+  { const uint32_t x23 = in2[0];
-+  out[0] = ((0x7ffffda + x5) - x23);
-+  out[1] = ((0x3fffffe + x7) - x25);
-+  out[2] = ((0x7fffffe + x9) - x27);
-+  out[3] = ((0x3fffffe + x11) - x29);
-+  out[4] = ((0x7fffffe + x13) - x31);
-+  out[5] = ((0x3fffffe + x15) - x33);
-+  out[6] = ((0x7fffffe + x17) - x35);
-+  out[7] = ((0x3fffffe + x19) - x37);
-+  out[8] = ((0x7fffffe + x21) - x39);
-+  out[9] = ((0x3fffffe + x20) - x38);
-+  }}}}}}}}}}}}}}}}}}}}
-+}
-+
-+// h = -f
-+static void fe_neg(fe_loose *h, const fe *f) {
-+  assert_fe(f->v);
-+  fe_neg_impl(h->v, f->v);
-+  assert_fe_loose(h->v);
-+}
-+
-+// Replace (f,g) with (g,g) if b == 1;
-+// replace (f,g) with (f,g) if b == 0.
-+//
-+// Preconditions: b in {0,1}.
-+static void fe_cmov(fe_loose *f, const fe_loose *g, unsigned b) {
-+  b = 0-b;
-+  unsigned i;
-+  for (i = 0; i < 10; i++) {
-+    uint32_t x = f->v[i] ^ g->v[i];
-+    x &= b;
-+    f->v[i] ^= x;
-+  }
-+}
-+
-+#endif  // BORINGSSL_CURVE25519_64BIT
-+
-+// h = f
-+static void fe_copy(fe *h, const fe *f) {
-+  memmove(h, f, sizeof(fe));
-+}
-+
-+static void fe_copy_lt(fe_loose *h, const fe *f) {
-+#ifdef EDWARDS25519_ASSERTS
-+  assert(sizeof(fe_loose) == sizeof(fe));
-+#endif
-+  memmove(h, f, sizeof(fe));
-+}
-+#if !defined(CONFIG_SMALL)
-+static void fe_copy_ll(fe_loose *h, const fe_loose *f) {
-+  memmove(h, f, sizeof(fe_loose));
-+}
-+#endif // !defined(CONFIG_SMALL)
-+
-+static void fe_loose_invert(fe *out, const fe_loose *z) {
-+  fe t0;
-+  fe t1;
-+  fe t2;
-+  fe t3;
-+  int i;
-+
-+  fe_sq_tl(&t0, z);
-+  fe_sq_tt(&t1, &t0);
-+  for (i = 1; i < 2; ++i) {
-+    fe_sq_tt(&t1, &t1);
-+  }
-+  fe_mul_tlt(&t1, z, &t1);
-+  fe_mul_ttt(&t0, &t0, &t1);
-+  fe_sq_tt(&t2, &t0);
-+  fe_mul_ttt(&t1, &t1, &t2);
-+  fe_sq_tt(&t2, &t1);
-+  for (i = 1; i < 5; ++i) {
-+    fe_sq_tt(&t2, &t2);
-+  }
-+  fe_mul_ttt(&t1, &t2, &t1);
-+  fe_sq_tt(&t2, &t1);
-+  for (i = 1; i < 10; ++i) {
-+    fe_sq_tt(&t2, &t2);
-+  }
-+  fe_mul_ttt(&t2, &t2, &t1);
-+  fe_sq_tt(&t3, &t2);
-+  for (i = 1; i < 20; ++i) {
-+    fe_sq_tt(&t3, &t3);
-+  }
-+  fe_mul_ttt(&t2, &t3, &t2);
-+  fe_sq_tt(&t2, &t2);
-+  for (i = 1; i < 10; ++i) {
-+    fe_sq_tt(&t2, &t2);
-+  }
-+  fe_mul_ttt(&t1, &t2, &t1);
-+  fe_sq_tt(&t2, &t1);
-+  for (i = 1; i < 50; ++i) {
-+    fe_sq_tt(&t2, &t2);
-+  }
-+  fe_mul_ttt(&t2, &t2, &t1);
-+  fe_sq_tt(&t3, &t2);
-+  for (i = 1; i < 100; ++i) {
-+    fe_sq_tt(&t3, &t3);
-+  }
-+  fe_mul_ttt(&t2, &t3, &t2);
-+  fe_sq_tt(&t2, &t2);
-+  for (i = 1; i < 50; ++i) {
-+    fe_sq_tt(&t2, &t2);
-+  }
-+  fe_mul_ttt(&t1, &t2, &t1);
-+  fe_sq_tt(&t1, &t1);
-+  for (i = 1; i < 5; ++i) {
-+    fe_sq_tt(&t1, &t1);
-+  }
-+  fe_mul_ttt(out, &t1, &t0);
-+}
-+
-+static void fe_invert(fe *out, const fe *z) {
-+  fe_loose l;
-+  fe_copy_lt(&l, z);
-+  fe_loose_invert(out, &l);
-+}
-+
-+// return 0 if f == 0
-+// return 1 if f != 0
-+static int fe_isnonzero(const fe_loose *f) {
-+  fe tight;
-+  fe_carry(&tight, f);
-+  uint8_t s[32];
-+  fe_tobytes(s, &tight);
-+
-+  static const uint8_t zero[32] = {0};
-+  return k5_bcmp(s, zero, sizeof(zero)) != 0;
-+}
-+
-+// return 1 if f is in {1,3,5,...,q-2}
-+// return 0 if f is in {0,2,4,...,q-1}
-+static int fe_isnegative(const fe *f) {
-+  uint8_t s[32];
-+  fe_tobytes(s, f);
-+  return s[0] & 1;
-+}
-+
-+static void fe_sq2_tt(fe *h, const fe *f) {
-+  // h = f^2
-+  fe_sq_tt(h, f);
-+
-+  // h = h + h
-+  fe_loose tmp;
-+  fe_add(&tmp, h, h);
-+  fe_carry(h, &tmp);
-+}
-+
-+static void fe_pow22523(fe *out, const fe *z) {
-+  fe t0;
-+  fe t1;
-+  fe t2;
-+  int i;
-+
-+  fe_sq_tt(&t0, z);
-+  fe_sq_tt(&t1, &t0);
-+  for (i = 1; i < 2; ++i) {
-+    fe_sq_tt(&t1, &t1);
-+  }
-+  fe_mul_ttt(&t1, z, &t1);
-+  fe_mul_ttt(&t0, &t0, &t1);
-+  fe_sq_tt(&t0, &t0);
-+  fe_mul_ttt(&t0, &t1, &t0);
-+  fe_sq_tt(&t1, &t0);
-+  for (i = 1; i < 5; ++i) {
-+    fe_sq_tt(&t1, &t1);
-+  }
-+  fe_mul_ttt(&t0, &t1, &t0);
-+  fe_sq_tt(&t1, &t0);
-+  for (i = 1; i < 10; ++i) {
-+    fe_sq_tt(&t1, &t1);
-+  }
-+  fe_mul_ttt(&t1, &t1, &t0);
-+  fe_sq_tt(&t2, &t1);
-+  for (i = 1; i < 20; ++i) {
-+    fe_sq_tt(&t2, &t2);
-+  }
-+  fe_mul_ttt(&t1, &t2, &t1);
-+  fe_sq_tt(&t1, &t1);
-+  for (i = 1; i < 10; ++i) {
-+    fe_sq_tt(&t1, &t1);
-+  }
-+  fe_mul_ttt(&t0, &t1, &t0);
-+  fe_sq_tt(&t1, &t0);
-+  for (i = 1; i < 50; ++i) {
-+    fe_sq_tt(&t1, &t1);
-+  }
-+  fe_mul_ttt(&t1, &t1, &t0);
-+  fe_sq_tt(&t2, &t1);
-+  for (i = 1; i < 100; ++i) {
-+    fe_sq_tt(&t2, &t2);
-+  }
-+  fe_mul_ttt(&t1, &t2, &t1);
-+  fe_sq_tt(&t1, &t1);
-+  for (i = 1; i < 50; ++i) {
-+    fe_sq_tt(&t1, &t1);
-+  }
-+  fe_mul_ttt(&t0, &t1, &t0);
-+  fe_sq_tt(&t0, &t0);
-+  for (i = 1; i < 2; ++i) {
-+    fe_sq_tt(&t0, &t0);
-+  }
-+  fe_mul_ttt(out, &t0, z);
-+}
-+
-+
-+// Group operations.
-+
-+static void x25519_ge_tobytes(uint8_t s[32], const ge_p2 *h) {
-+  fe recip;
-+  fe x;
-+  fe y;
-+
-+  fe_invert(&recip, &h->Z);
-+  fe_mul_ttt(&x, &h->X, &recip);
-+  fe_mul_ttt(&y, &h->Y, &recip);
-+  fe_tobytes(s, &y);
-+  s[31] ^= fe_isnegative(&x) << 7;
-+}
-+
-+static int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t *s) {
-+  fe u;
-+  fe_loose v;
-+  fe v3;
-+  fe vxx;
-+  fe_loose check;
-+
-+  fe_frombytes(&h->Y, s);
-+  fe_1(&h->Z);
-+  fe_sq_tt(&v3, &h->Y);
-+  fe_mul_ttt(&vxx, &v3, &d);
-+  fe_sub(&v, &v3, &h->Z);  // u = y^2-1
-+  fe_carry(&u, &v);
-+  fe_add(&v, &vxx, &h->Z);  // v = dy^2+1
-+
-+  fe_sq_tl(&v3, &v);
-+  fe_mul_ttl(&v3, &v3, &v);  // v3 = v^3
-+  fe_sq_tt(&h->X, &v3);
-+  fe_mul_ttl(&h->X, &h->X, &v);
-+  fe_mul_ttt(&h->X, &h->X, &u);  // x = uv^7
-+
-+  fe_pow22523(&h->X, &h->X);  // x = (uv^7)^((q-5)/8)
-+  fe_mul_ttt(&h->X, &h->X, &v3);
-+  fe_mul_ttt(&h->X, &h->X, &u);  // x = uv^3(uv^7)^((q-5)/8)
-+
-+  fe_sq_tt(&vxx, &h->X);
-+  fe_mul_ttl(&vxx, &vxx, &v);
-+  fe_sub(&check, &vxx, &u);
-+  if (fe_isnonzero(&check)) {
-+    fe_add(&check, &vxx, &u);
-+    if (fe_isnonzero(&check)) {
-+      return -1;
-+    }
-+    fe_mul_ttt(&h->X, &h->X, &sqrtm1);
-+  }
-+
-+  if (fe_isnegative(&h->X) != (s[31] >> 7)) {
-+    fe_loose t;
-+    fe_neg(&t, &h->X);
-+    fe_carry(&h->X, &t);
-+  }
-+
-+  fe_mul_ttt(&h->T, &h->X, &h->Y);
-+  return 0;
-+}
-+
-+static void ge_p2_0(ge_p2 *h) {
-+  fe_0(&h->X);
-+  fe_1(&h->Y);
-+  fe_1(&h->Z);
-+}
-+
-+static void ge_p3_0(ge_p3 *h) {
-+  fe_0(&h->X);
-+  fe_1(&h->Y);
-+  fe_1(&h->Z);
-+  fe_0(&h->T);
-+}
-+
-+static void ge_cached_0(ge_cached *h) {
-+  fe_loose_1(&h->YplusX);
-+  fe_loose_1(&h->YminusX);
-+  fe_loose_1(&h->Z);
-+  fe_loose_0(&h->T2d);
-+}
-+
-+static void ge_precomp_0(ge_precomp *h) {
-+  fe_loose_1(&h->yplusx);
-+  fe_loose_1(&h->yminusx);
-+  fe_loose_0(&h->xy2d);
-+}
-+
-+// r = p
-+static void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) {
-+  fe_copy(&r->X, &p->X);
-+  fe_copy(&r->Y, &p->Y);
-+  fe_copy(&r->Z, &p->Z);
-+}
-+
-+// r = p
-+static void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {
-+  fe_add(&r->YplusX, &p->Y, &p->X);
-+  fe_sub(&r->YminusX, &p->Y, &p->X);
-+  fe_copy_lt(&r->Z, &p->Z);
-+  fe_mul_ltt(&r->T2d, &p->T, &d2);
-+}
-+
-+// r = p
-+static void x25519_ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) {
-+  fe_mul_tll(&r->X, &p->X, &p->T);
-+  fe_mul_tll(&r->Y, &p->Y, &p->Z);
-+  fe_mul_tll(&r->Z, &p->Z, &p->T);
-+}
-+
-+// r = p
-+static void x25519_ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) {
-+  fe_mul_tll(&r->X, &p->X, &p->T);
-+  fe_mul_tll(&r->Y, &p->Y, &p->Z);
-+  fe_mul_tll(&r->Z, &p->Z, &p->T);
-+  fe_mul_tll(&r->T, &p->X, &p->Y);
-+}
-+
-+// r = p
-+static void ge_p1p1_to_cached(ge_cached *r, const ge_p1p1 *p) {
-+  ge_p3 t;
-+  x25519_ge_p1p1_to_p3(&t, p);
-+  x25519_ge_p3_to_cached(r, &t);
-+}
-+
-+// r = 2 * p
-+static void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) {
-+  fe trX, trZ, trT;
-+  fe t0;
-+
-+  fe_sq_tt(&trX, &p->X);
-+  fe_sq_tt(&trZ, &p->Y);
-+  fe_sq2_tt(&trT, &p->Z);
-+  fe_add(&r->Y, &p->X, &p->Y);
-+  fe_sq_tl(&t0, &r->Y);
-+
-+  fe_add(&r->Y, &trZ, &trX);
-+  fe_sub(&r->Z, &trZ, &trX);
-+  fe_carry(&trZ, &r->Y);
-+  fe_sub(&r->X, &t0, &trZ);
-+  fe_carry(&trZ, &r->Z);
-+  fe_sub(&r->T, &trT, &trZ);
-+}
-+
-+#ifndef CONFIG_SMALL
-+// r = 2 * p
-+static void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) {
-+  ge_p2 q;
-+  ge_p3_to_p2(&q, p);
-+  ge_p2_dbl(r, &q);
-+}
-+#endif
-+
-+// r = p + q
-+static void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
-+  fe trY, trZ, trT;
-+
-+  fe_add(&r->X, &p->Y, &p->X);
-+  fe_sub(&r->Y, &p->Y, &p->X);
-+  fe_mul_tll(&trZ, &r->X, &q->yplusx);
-+  fe_mul_tll(&trY, &r->Y, &q->yminusx);
-+  fe_mul_tlt(&trT, &q->xy2d, &p->T);
-+  fe_add(&r->T, &p->Z, &p->Z);
-+  fe_sub(&r->X, &trZ, &trY);
-+  fe_add(&r->Y, &trZ, &trY);
-+  fe_carry(&trZ, &r->T);
-+  fe_add(&r->Z, &trZ, &trT);
-+  fe_sub(&r->T, &trZ, &trT);
-+}
-+
-+// r = p + q
-+static void x25519_ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
-+  fe trX, trY, trZ, trT;
-+
-+  fe_add(&r->X, &p->Y, &p->X);
-+  fe_sub(&r->Y, &p->Y, &p->X);
-+  fe_mul_tll(&trZ, &r->X, &q->YplusX);
-+  fe_mul_tll(&trY, &r->Y, &q->YminusX);
-+  fe_mul_tlt(&trT, &q->T2d, &p->T);
-+  fe_mul_ttl(&trX, &p->Z, &q->Z);
-+  fe_add(&r->T, &trX, &trX);
-+  fe_sub(&r->X, &trZ, &trY);
-+  fe_add(&r->Y, &trZ, &trY);
-+  fe_carry(&trZ, &r->T);
-+  fe_add(&r->Z, &trZ, &trT);
-+  fe_sub(&r->T, &trZ, &trT);
-+}
-+
-+// r = p - q
-+static void x25519_ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
-+  fe trX, trY, trZ, trT;
-+
-+  fe_add(&r->X, &p->Y, &p->X);
-+  fe_sub(&r->Y, &p->Y, &p->X);
-+  fe_mul_tll(&trZ, &r->X, &q->YminusX);
-+  fe_mul_tll(&trY, &r->Y, &q->YplusX);
-+  fe_mul_tlt(&trT, &q->T2d, &p->T);
-+  fe_mul_ttl(&trX, &p->Z, &q->Z);
-+  fe_add(&r->T, &trX, &trX);
-+  fe_sub(&r->X, &trZ, &trY);
-+  fe_add(&r->Y, &trZ, &trY);
-+  fe_carry(&trZ, &r->T);
-+  fe_sub(&r->Z, &trZ, &trT);
-+  fe_add(&r->T, &trZ, &trT);
-+}
-+
-+static uint8_t equal(signed char b, signed char c) {
-+  uint8_t ub = b;
-+  uint8_t uc = c;
-+  uint8_t x = ub ^ uc;  // 0: yes; 1..255: no
-+  uint32_t y = x;       // 0: yes; 1..255: no
-+  y -= 1;               // 4294967295: yes; 0..254: no
-+  y >>= 31;             // 1: yes; 0: no
-+  return y;
-+}
-+
-+static void cmov(ge_precomp *t, const ge_precomp *u, uint8_t b) {
-+  fe_cmov(&t->yplusx, &u->yplusx, b);
-+  fe_cmov(&t->yminusx, &u->yminusx, b);
-+  fe_cmov(&t->xy2d, &u->xy2d, b);
-+}
-+
-+static void x25519_ge_scalarmult_small_precomp(
-+    ge_p3 *h, const uint8_t a[32], const uint8_t precomp_table[15 * 2 * 32]) {
-+  // precomp_table is first expanded into matching |ge_precomp|
-+  // elements.
-+  ge_precomp multiples[15];
-+
-+  unsigned i;
-+  for (i = 0; i < 15; i++) {
-+    const uint8_t *bytes = &precomp_table[i*(2 * 32)];
-+    fe x, y;
-+    fe_frombytes(&x, bytes);
-+    fe_frombytes(&y, bytes + 32);
-+
-+    ge_precomp *out = &multiples[i];
-+    fe_add(&out->yplusx, &y, &x);
-+    fe_sub(&out->yminusx, &y, &x);
-+    fe_mul_ltt(&out->xy2d, &x, &y);
-+    fe_mul_llt(&out->xy2d, &out->xy2d, &d2);
-+  }
-+
-+  // See the comment above |k25519SmallPrecomp| about the structure of the
-+  // precomputed elements. This loop does 64 additions and 64 doublings to
-+  // calculate the result.
-+  ge_p3_0(h);
-+
-+  for (i = 63; i < 64; i--) {
-+    unsigned j;
-+    signed char index = 0;
-+
-+    for (j = 0; j < 4; j++) {
-+      const uint8_t bit = 1 & (a[(8 * j) + (i / 8)] >> (i & 7));
-+      index |= (bit << j);
-+    }
-+
-+    ge_precomp e;
-+    ge_precomp_0(&e);
-+
-+    for (j = 1; j < 16; j++) {
-+      cmov(&e, &multiples[j-1], equal(index, j));
-+    }
-+
-+    ge_cached cached;
-+    ge_p1p1 r;
-+    x25519_ge_p3_to_cached(&cached, h);
-+    x25519_ge_add(&r, h, &cached);
-+    x25519_ge_p1p1_to_p3(h, &r);
-+
-+    ge_madd(&r, h, &e);
-+    x25519_ge_p1p1_to_p3(h, &r);
-+  }
-+}
-+
-+#if defined(CONFIG_SMALL)
-+
-+static void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]) {
-+  x25519_ge_scalarmult_small_precomp(h, a, k25519SmallPrecomp);
-+}
-+
-+#else
-+
-+static uint8_t negative(signed char b) {
-+  uint32_t x = b;
-+  x >>= 31;  // 1: yes; 0: no
-+  return x;
-+}
-+
-+static void table_select(ge_precomp *t, int pos, signed char b) {
-+  ge_precomp minust;
-+  uint8_t bnegative = negative(b);
-+  uint8_t babs = b - ((uint8_t)((-bnegative) & b) << 1);
-+
-+  ge_precomp_0(t);
-+  cmov(t, &k25519Precomp[pos][0], equal(babs, 1));
-+  cmov(t, &k25519Precomp[pos][1], equal(babs, 2));
-+  cmov(t, &k25519Precomp[pos][2], equal(babs, 3));
-+  cmov(t, &k25519Precomp[pos][3], equal(babs, 4));
-+  cmov(t, &k25519Precomp[pos][4], equal(babs, 5));
-+  cmov(t, &k25519Precomp[pos][5], equal(babs, 6));
-+  cmov(t, &k25519Precomp[pos][6], equal(babs, 7));
-+  cmov(t, &k25519Precomp[pos][7], equal(babs, 8));
-+  fe_copy_ll(&minust.yplusx, &t->yminusx);
-+  fe_copy_ll(&minust.yminusx, &t->yplusx);
-+
-+  // NOTE: the input table is canonical, but types don't encode it
-+  fe tmp;
-+  fe_carry(&tmp, &t->xy2d);
-+  fe_neg(&minust.xy2d, &tmp);
-+
-+  cmov(t, &minust, bnegative);
-+}
-+
-+// h = a * B
-+// where a = a[0]+256*a[1]+...+256^31 a[31]
-+// B is the Ed25519 base point (x,4/5) with x positive.
-+//
-+// Preconditions:
-+//   a[31] <= 127
-+static void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t *a) {
-+  signed char e[64];
-+  signed char carry;
-+  ge_p1p1 r;
-+  ge_p2 s;
-+  ge_precomp t;
-+  int i;
-+
-+  for (i = 0; i < 32; ++i) {
-+    e[2 * i + 0] = (a[i] >> 0) & 15;
-+    e[2 * i + 1] = (a[i] >> 4) & 15;
-+  }
-+  // each e[i] is between 0 and 15
-+  // e[63] is between 0 and 7
-+
-+  carry = 0;
-+  for (i = 0; i < 63; ++i) {
-+    e[i] += carry;
-+    carry = e[i] + 8;
-+    carry >>= 4;
-+    e[i] -= carry << 4;
-+  }
-+  e[63] += carry;
-+  // each e[i] is between -8 and 8
-+
-+  ge_p3_0(h);
-+  for (i = 1; i < 64; i += 2) {
-+    table_select(&t, i / 2, e[i]);
-+    ge_madd(&r, h, &t);
-+    x25519_ge_p1p1_to_p3(h, &r);
-+  }
-+
-+  ge_p3_dbl(&r, h);
-+  x25519_ge_p1p1_to_p2(&s, &r);
-+  ge_p2_dbl(&r, &s);
-+  x25519_ge_p1p1_to_p2(&s, &r);
-+  ge_p2_dbl(&r, &s);
-+  x25519_ge_p1p1_to_p2(&s, &r);
-+  ge_p2_dbl(&r, &s);
-+  x25519_ge_p1p1_to_p3(h, &r);
-+
-+  for (i = 0; i < 64; i += 2) {
-+    table_select(&t, i / 2, e[i]);
-+    ge_madd(&r, h, &t);
-+    x25519_ge_p1p1_to_p3(h, &r);
-+  }
-+}
-+
-+#endif
-+
-+static void cmov_cached(ge_cached *t, ge_cached *u, uint8_t b) {
-+  fe_cmov(&t->YplusX, &u->YplusX, b);
-+  fe_cmov(&t->YminusX, &u->YminusX, b);
-+  fe_cmov(&t->Z, &u->Z, b);
-+  fe_cmov(&t->T2d, &u->T2d, b);
-+}
-+
-+// r = scalar * A.
-+// where a = a[0]+256*a[1]+...+256^31 a[31].
-+static void x25519_ge_scalarmult(ge_p2 *r, const uint8_t *scalar,
-+                                 const ge_p3 *A) {
-+  ge_p2 Ai_p2[8];
-+  ge_cached Ai[16];
-+  ge_p1p1 t;
-+
-+  ge_cached_0(&Ai[0]);
-+  x25519_ge_p3_to_cached(&Ai[1], A);
-+  ge_p3_to_p2(&Ai_p2[1], A);
-+
-+  unsigned i;
-+  for (i = 2; i < 16; i += 2) {
-+    ge_p2_dbl(&t, &Ai_p2[i / 2]);
-+    ge_p1p1_to_cached(&Ai[i], &t);
-+    if (i < 8) {
-+      x25519_ge_p1p1_to_p2(&Ai_p2[i], &t);
-+    }
-+    x25519_ge_add(&t, A, &Ai[i]);
-+    ge_p1p1_to_cached(&Ai[i + 1], &t);
-+    if (i < 7) {
-+      x25519_ge_p1p1_to_p2(&Ai_p2[i + 1], &t);
-+    }
-+  }
-+
-+  ge_p2_0(r);
-+  ge_p3 u;
-+
-+  for (i = 0; i < 256; i += 4) {
-+    ge_p2_dbl(&t, r);
-+    x25519_ge_p1p1_to_p2(r, &t);
-+    ge_p2_dbl(&t, r);
-+    x25519_ge_p1p1_to_p2(r, &t);
-+    ge_p2_dbl(&t, r);
-+    x25519_ge_p1p1_to_p2(r, &t);
-+    ge_p2_dbl(&t, r);
-+    x25519_ge_p1p1_to_p3(&u, &t);
-+
-+    uint8_t index = scalar[31 - i/8];
-+    index >>= 4 - (i & 4);
-+    index &= 0xf;
-+
-+    unsigned j;
-+    ge_cached selected;
-+    ge_cached_0(&selected);
-+    for (j = 0; j < 16; j++) {
-+      cmov_cached(&selected, &Ai[j], equal(j, index));
-+    }
-+
-+    x25519_ge_add(&t, &u, &selected);
-+    x25519_ge_p1p1_to_p2(r, &t);
-+  }
-+}
-+
-+// The set of scalars is \Z/l
-+// where l = 2^252 + 27742317777372353535851937790883648493.
-+
-+// Input:
-+//   s[0]+256*s[1]+...+256^63*s[63] = s
-+//
-+// Output:
-+//   s[0]+256*s[1]+...+256^31*s[31] = s mod l
-+//   where l = 2^252 + 27742317777372353535851937790883648493.
-+//   Overwrites s in place.
-+static void x25519_sc_reduce(uint8_t s[64]) {
-+  int64_t s0 = 2097151 & load_3(s);
-+  int64_t s1 = 2097151 & (load_4(s + 2) >> 5);
-+  int64_t s2 = 2097151 & (load_3(s + 5) >> 2);
-+  int64_t s3 = 2097151 & (load_4(s + 7) >> 7);
-+  int64_t s4 = 2097151 & (load_4(s + 10) >> 4);
-+  int64_t s5 = 2097151 & (load_3(s + 13) >> 1);
-+  int64_t s6 = 2097151 & (load_4(s + 15) >> 6);
-+  int64_t s7 = 2097151 & (load_3(s + 18) >> 3);
-+  int64_t s8 = 2097151 & load_3(s + 21);
-+  int64_t s9 = 2097151 & (load_4(s + 23) >> 5);
-+  int64_t s10 = 2097151 & (load_3(s + 26) >> 2);
-+  int64_t s11 = 2097151 & (load_4(s + 28) >> 7);
-+  int64_t s12 = 2097151 & (load_4(s + 31) >> 4);
-+  int64_t s13 = 2097151 & (load_3(s + 34) >> 1);
-+  int64_t s14 = 2097151 & (load_4(s + 36) >> 6);
-+  int64_t s15 = 2097151 & (load_3(s + 39) >> 3);
-+  int64_t s16 = 2097151 & load_3(s + 42);
-+  int64_t s17 = 2097151 & (load_4(s + 44) >> 5);
-+  int64_t s18 = 2097151 & (load_3(s + 47) >> 2);
-+  int64_t s19 = 2097151 & (load_4(s + 49) >> 7);
-+  int64_t s20 = 2097151 & (load_4(s + 52) >> 4);
-+  int64_t s21 = 2097151 & (load_3(s + 55) >> 1);
-+  int64_t s22 = 2097151 & (load_4(s + 57) >> 6);
-+  int64_t s23 = (load_4(s + 60) >> 3);
-+  int64_t carry0;
-+  int64_t carry1;
-+  int64_t carry2;
-+  int64_t carry3;
-+  int64_t carry4;
-+  int64_t carry5;
-+  int64_t carry6;
-+  int64_t carry7;
-+  int64_t carry8;
-+  int64_t carry9;
-+  int64_t carry10;
-+  int64_t carry11;
-+  int64_t carry12;
-+  int64_t carry13;
-+  int64_t carry14;
-+  int64_t carry15;
-+  int64_t carry16;
-+
-+  s11 += s23 * 666643;
-+  s12 += s23 * 470296;
-+  s13 += s23 * 654183;
-+  s14 -= s23 * 997805;
-+  s15 += s23 * 136657;
-+  s16 -= s23 * 683901;
-+  s23 = 0;
-+
-+  s10 += s22 * 666643;
-+  s11 += s22 * 470296;
-+  s12 += s22 * 654183;
-+  s13 -= s22 * 997805;
-+  s14 += s22 * 136657;
-+  s15 -= s22 * 683901;
-+  s22 = 0;
-+
-+  s9 += s21 * 666643;
-+  s10 += s21 * 470296;
-+  s11 += s21 * 654183;
-+  s12 -= s21 * 997805;
-+  s13 += s21 * 136657;
-+  s14 -= s21 * 683901;
-+  s21 = 0;
-+
-+  s8 += s20 * 666643;
-+  s9 += s20 * 470296;
-+  s10 += s20 * 654183;
-+  s11 -= s20 * 997805;
-+  s12 += s20 * 136657;
-+  s13 -= s20 * 683901;
-+  s20 = 0;
-+
-+  s7 += s19 * 666643;
-+  s8 += s19 * 470296;
-+  s9 += s19 * 654183;
-+  s10 -= s19 * 997805;
-+  s11 += s19 * 136657;
-+  s12 -= s19 * 683901;
-+  s19 = 0;
-+
-+  s6 += s18 * 666643;
-+  s7 += s18 * 470296;
-+  s8 += s18 * 654183;
-+  s9 -= s18 * 997805;
-+  s10 += s18 * 136657;
-+  s11 -= s18 * 683901;
-+  s18 = 0;
-+
-+  carry6 = (s6 + (1 << 20)) >> 21;
-+  s7 += carry6;
-+  s6 -= carry6 << 21;
-+  carry8 = (s8 + (1 << 20)) >> 21;
-+  s9 += carry8;
-+  s8 -= carry8 << 21;
-+  carry10 = (s10 + (1 << 20)) >> 21;
-+  s11 += carry10;
-+  s10 -= carry10 << 21;
-+  carry12 = (s12 + (1 << 20)) >> 21;
-+  s13 += carry12;
-+  s12 -= carry12 << 21;
-+  carry14 = (s14 + (1 << 20)) >> 21;
-+  s15 += carry14;
-+  s14 -= carry14 << 21;
-+  carry16 = (s16 + (1 << 20)) >> 21;
-+  s17 += carry16;
-+  s16 -= carry16 << 21;
-+
-+  carry7 = (s7 + (1 << 20)) >> 21;
-+  s8 += carry7;
-+  s7 -= carry7 << 21;
-+  carry9 = (s9 + (1 << 20)) >> 21;
-+  s10 += carry9;
-+  s9 -= carry9 << 21;
-+  carry11 = (s11 + (1 << 20)) >> 21;
-+  s12 += carry11;
-+  s11 -= carry11 << 21;
-+  carry13 = (s13 + (1 << 20)) >> 21;
-+  s14 += carry13;
-+  s13 -= carry13 << 21;
-+  carry15 = (s15 + (1 << 20)) >> 21;
-+  s16 += carry15;
-+  s15 -= carry15 << 21;
-+
-+  s5 += s17 * 666643;
-+  s6 += s17 * 470296;
-+  s7 += s17 * 654183;
-+  s8 -= s17 * 997805;
-+  s9 += s17 * 136657;
-+  s10 -= s17 * 683901;
-+  s17 = 0;
-+
-+  s4 += s16 * 666643;
-+  s5 += s16 * 470296;
-+  s6 += s16 * 654183;
-+  s7 -= s16 * 997805;
-+  s8 += s16 * 136657;
-+  s9 -= s16 * 683901;
-+  s16 = 0;
-+
-+  s3 += s15 * 666643;
-+  s4 += s15 * 470296;
-+  s5 += s15 * 654183;
-+  s6 -= s15 * 997805;
-+  s7 += s15 * 136657;
-+  s8 -= s15 * 683901;
-+  s15 = 0;
-+
-+  s2 += s14 * 666643;
-+  s3 += s14 * 470296;
-+  s4 += s14 * 654183;
-+  s5 -= s14 * 997805;
-+  s6 += s14 * 136657;
-+  s7 -= s14 * 683901;
-+  s14 = 0;
-+
-+  s1 += s13 * 666643;
-+  s2 += s13 * 470296;
-+  s3 += s13 * 654183;
-+  s4 -= s13 * 997805;
-+  s5 += s13 * 136657;
-+  s6 -= s13 * 683901;
-+  s13 = 0;
-+
-+  s0 += s12 * 666643;
-+  s1 += s12 * 470296;
-+  s2 += s12 * 654183;
-+  s3 -= s12 * 997805;
-+  s4 += s12 * 136657;
-+  s5 -= s12 * 683901;
-+  s12 = 0;
-+
-+  carry0 = (s0 + (1 << 20)) >> 21;
-+  s1 += carry0;
-+  s0 -= carry0 << 21;
-+  carry2 = (s2 + (1 << 20)) >> 21;
-+  s3 += carry2;
-+  s2 -= carry2 << 21;
-+  carry4 = (s4 + (1 << 20)) >> 21;
-+  s5 += carry4;
-+  s4 -= carry4 << 21;
-+  carry6 = (s6 + (1 << 20)) >> 21;
-+  s7 += carry6;
-+  s6 -= carry6 << 21;
-+  carry8 = (s8 + (1 << 20)) >> 21;
-+  s9 += carry8;
-+  s8 -= carry8 << 21;
-+  carry10 = (s10 + (1 << 20)) >> 21;
-+  s11 += carry10;
-+  s10 -= carry10 << 21;
-+
-+  carry1 = (s1 + (1 << 20)) >> 21;
-+  s2 += carry1;
-+  s1 -= carry1 << 21;
-+  carry3 = (s3 + (1 << 20)) >> 21;
-+  s4 += carry3;
-+  s3 -= carry3 << 21;
-+  carry5 = (s5 + (1 << 20)) >> 21;
-+  s6 += carry5;
-+  s5 -= carry5 << 21;
-+  carry7 = (s7 + (1 << 20)) >> 21;
-+  s8 += carry7;
-+  s7 -= carry7 << 21;
-+  carry9 = (s9 + (1 << 20)) >> 21;
-+  s10 += carry9;
-+  s9 -= carry9 << 21;
-+  carry11 = (s11 + (1 << 20)) >> 21;
-+  s12 += carry11;
-+  s11 -= carry11 << 21;
-+
-+  s0 += s12 * 666643;
-+  s1 += s12 * 470296;
-+  s2 += s12 * 654183;
-+  s3 -= s12 * 997805;
-+  s4 += s12 * 136657;
-+  s5 -= s12 * 683901;
-+  s12 = 0;
-+
-+  carry0 = s0 >> 21;
-+  s1 += carry0;
-+  s0 -= carry0 << 21;
-+  carry1 = s1 >> 21;
-+  s2 += carry1;
-+  s1 -= carry1 << 21;
-+  carry2 = s2 >> 21;
-+  s3 += carry2;
-+  s2 -= carry2 << 21;
-+  carry3 = s3 >> 21;
-+  s4 += carry3;
-+  s3 -= carry3 << 21;
-+  carry4 = s4 >> 21;
-+  s5 += carry4;
-+  s4 -= carry4 << 21;
-+  carry5 = s5 >> 21;
-+  s6 += carry5;
-+  s5 -= carry5 << 21;
-+  carry6 = s6 >> 21;
-+  s7 += carry6;
-+  s6 -= carry6 << 21;
-+  carry7 = s7 >> 21;
-+  s8 += carry7;
-+  s7 -= carry7 << 21;
-+  carry8 = s8 >> 21;
-+  s9 += carry8;
-+  s8 -= carry8 << 21;
-+  carry9 = s9 >> 21;
-+  s10 += carry9;
-+  s9 -= carry9 << 21;
-+  carry10 = s10 >> 21;
-+  s11 += carry10;
-+  s10 -= carry10 << 21;
-+  carry11 = s11 >> 21;
-+  s12 += carry11;
-+  s11 -= carry11 << 21;
-+
-+  s0 += s12 * 666643;
-+  s1 += s12 * 470296;
-+  s2 += s12 * 654183;
-+  s3 -= s12 * 997805;
-+  s4 += s12 * 136657;
-+  s5 -= s12 * 683901;
-+  s12 = 0;
-+
-+  carry0 = s0 >> 21;
-+  s1 += carry0;
-+  s0 -= carry0 << 21;
-+  carry1 = s1 >> 21;
-+  s2 += carry1;
-+  s1 -= carry1 << 21;
-+  carry2 = s2 >> 21;
-+  s3 += carry2;
-+  s2 -= carry2 << 21;
-+  carry3 = s3 >> 21;
-+  s4 += carry3;
-+  s3 -= carry3 << 21;
-+  carry4 = s4 >> 21;
-+  s5 += carry4;
-+  s4 -= carry4 << 21;
-+  carry5 = s5 >> 21;
-+  s6 += carry5;
-+  s5 -= carry5 << 21;
-+  carry6 = s6 >> 21;
-+  s7 += carry6;
-+  s6 -= carry6 << 21;
-+  carry7 = s7 >> 21;
-+  s8 += carry7;
-+  s7 -= carry7 << 21;
-+  carry8 = s8 >> 21;
-+  s9 += carry8;
-+  s8 -= carry8 << 21;
-+  carry9 = s9 >> 21;
-+  s10 += carry9;
-+  s9 -= carry9 << 21;
-+  carry10 = s10 >> 21;
-+  s11 += carry10;
-+  s10 -= carry10 << 21;
-+
-+  s[0] = s0 >> 0;
-+  s[1] = s0 >> 8;
-+  s[2] = (s0 >> 16) | (s1 << 5);
-+  s[3] = s1 >> 3;
-+  s[4] = s1 >> 11;
-+  s[5] = (s1 >> 19) | (s2 << 2);
-+  s[6] = s2 >> 6;
-+  s[7] = (s2 >> 14) | (s3 << 7);
-+  s[8] = s3 >> 1;
-+  s[9] = s3 >> 9;
-+  s[10] = (s3 >> 17) | (s4 << 4);
-+  s[11] = s4 >> 4;
-+  s[12] = s4 >> 12;
-+  s[13] = (s4 >> 20) | (s5 << 1);
-+  s[14] = s5 >> 7;
-+  s[15] = (s5 >> 15) | (s6 << 6);
-+  s[16] = s6 >> 2;
-+  s[17] = s6 >> 10;
-+  s[18] = (s6 >> 18) | (s7 << 3);
-+  s[19] = s7 >> 5;
-+  s[20] = s7 >> 13;
-+  s[21] = s8 >> 0;
-+  s[22] = s8 >> 8;
-+  s[23] = (s8 >> 16) | (s9 << 5);
-+  s[24] = s9 >> 3;
-+  s[25] = s9 >> 11;
-+  s[26] = (s9 >> 19) | (s10 << 2);
-+  s[27] = s10 >> 6;
-+  s[28] = (s10 >> 14) | (s11 << 7);
-+  s[29] = s11 >> 1;
-+  s[30] = s11 >> 9;
-+  s[31] = s11 >> 17;
-+}
-+
-+/* Loosely from BoringSSL crypto/curve25519/spake25519.c */
-+
-+/*
-+ * Here BoringSSL uses different points, not restricted to the generator
-+ * subgroup, while we use the draft-irtf-cfrg-spake2-05 points.  The Python
-+ * code is modified to add the subgroup restriction.
-+ */
-+
-+// The following precomputation tables are for the following
-+// points:
-+//
-+// N (found in 7 iterations):
-+//   x: 10742253510813957597047979962966927467575235974254765187031601461055699024931
-+//   y: 19796686047937480651099107989427797822652529149428697746066532921705571401683
-+//   encoded: d3bfb518f44f3430f29d0c92af503865a1ed3281dc69b35dd868ba85f886c4ab
-+//
-+// M (found in 21 iterations):
-+//   x: 8158688967149231307266666683326742915289288280191350817196911733632187385319
-+//   y: 21622333750659878624441478467798461427617029906629724657331223068277098105040
-+//   encoded: d048032c6ea0b6d697ddc2e86bda85a33adac920f1bf18e1b0c6d166a5cecdaf
-+//
-+// These points and their precomputation tables are generated with the
-+// following Python code.
-+
-+/*
-+import hashlib
-+import ed25519 as E  # http://ed25519.cr.yp.to/python/ed25519.py
-+
-+SEED_N = 'edwards25519 point generation seed (N)'
-+SEED_M = 'edwards25519 point generation seed (M)'
-+
-+def genpoint(seed):
-+    v = hashlib.sha256(seed).digest()
-+    it = 1
-+    while True:
-+        try:
-+            x,y = E.decodepoint(v)
-+            if E.scalarmult((x,y), E.l) != [0, 1]:
-+                raise Exception('point has wrong order')
-+        except Exception, e:
-+            print e
-+            it += 1
-+            v = hashlib.sha256(v).digest()
-+            continue
-+        print "Found in %d iterations:" % it
-+        print "  x = %d" % x
-+        print "  y = %d" % y
-+        print " Encoded (hex)"
-+        print E.encodepoint((x,y)).encode('hex')
-+        return (x,y)
-+
-+def gentable(P):
-+    t = []
-+    for i in range(1,16):
-+        k = (i >> 3 & 1) * (1 << 192) + \
-+            (i >> 2 & 1) * (1 << 128) + \
-+            (i >> 1 & 1) * (1 <<  64) + \
-+            (i      & 1)
-+        t.append(E.scalarmult(P, k))
-+    return ''.join(E.encodeint(x) + E.encodeint(y) for (x,y) in t)
-+
-+def printtable(table, name):
-+    print "static const uint8_t %s[15 * 2 * 32] = {" % name,
-+    for i in range(15 * 2 * 32):
-+        if i % 12 == 0:
-+            print "\n   ",
-+        print " 0x%02x," % ord(table[i]),
-+    print "\n};"
-+
-+if __name__ == "__main__":
-+    print "Searching for N"
-+    N = genpoint(SEED_N)
-+    print "Generating precomputation table for N"
-+    Ntable = gentable(N)
-+    printtable(Ntable, "kSpakeNSmallPrecomp")
-+
-+    print "Searching for M"
-+    M = genpoint(SEED_M)
-+    print "Generating precomputation table for M"
-+    Mtable = gentable(M)
-+    printtable(Mtable, "kSpakeMSmallPrecomp")
-+*/
-+
-+static const uint8_t kSpakeNSmallPrecomp[15 * 2 * 32] = {
-+    0x23, 0xfc, 0x27, 0x6c, 0x55, 0xaf, 0xb3, 0x9c, 0xd8, 0x99, 0x3a, 0x0d,
-+    0x7f, 0x08, 0xc9, 0xeb, 0x4d, 0x6e, 0x90, 0x99, 0x2f, 0x3c, 0x15, 0x2b,
-+    0x89, 0x5a, 0x0f, 0xf2, 0x67, 0xe6, 0xbf, 0x17, 0xd3, 0xbf, 0xb5, 0x18,
-+    0xf4, 0x4f, 0x34, 0x30, 0xf2, 0x9d, 0x0c, 0x92, 0xaf, 0x50, 0x38, 0x65,
-+    0xa1, 0xed, 0x32, 0x81, 0xdc, 0x69, 0xb3, 0x5d, 0xd8, 0x68, 0xba, 0x85,
-+    0xf8, 0x86, 0xc4, 0x2b, 0x53, 0x93, 0xb1, 0x99, 0x90, 0x30, 0xca, 0xb0,
-+    0xbd, 0xea, 0x14, 0x4c, 0x6f, 0x2b, 0x81, 0x1e, 0x23, 0x45, 0xb2, 0x32,
-+    0x2e, 0x2d, 0xe6, 0xb8, 0x5d, 0xc5, 0x15, 0x91, 0x63, 0x39, 0x18, 0x5b,
-+    0x62, 0x63, 0x9b, 0xf4, 0x8b, 0xe0, 0x34, 0xa2, 0x95, 0x11, 0x92, 0x68,
-+    0x54, 0xb7, 0xf3, 0x91, 0xca, 0x22, 0xad, 0x08, 0xd8, 0x9c, 0xa2, 0xf0,
-+    0xdc, 0x9c, 0x2c, 0x84, 0x32, 0x26, 0xe0, 0x17, 0x89, 0x53, 0x6b, 0xfd,
-+    0x76, 0x97, 0x25, 0xea, 0x99, 0x94, 0xf8, 0x29, 0x7c, 0xc4, 0x53, 0xc0,
-+    0x98, 0x9a, 0x20, 0xdc, 0x70, 0x01, 0x50, 0xaa, 0x05, 0xa3, 0x40, 0x50,
-+    0x66, 0x87, 0x30, 0x19, 0x12, 0xc3, 0xb8, 0x2d, 0x28, 0x8b, 0x7b, 0x48,
-+    0xf7, 0x7b, 0xab, 0x45, 0x70, 0x2e, 0xbb, 0x85, 0xc1, 0x6c, 0xdd, 0x35,
-+    0x00, 0x83, 0x20, 0x13, 0x82, 0x08, 0xaa, 0xa3, 0x03, 0x0f, 0xca, 0x27,
-+    0x3e, 0x8b, 0x52, 0xc2, 0xd7, 0xb1, 0x8c, 0x22, 0xfe, 0x04, 0x4a, 0xf2,
-+    0xe8, 0xac, 0xee, 0x2e, 0xd7, 0x77, 0x34, 0x49, 0xf2, 0xe9, 0xeb, 0x8c,
-+    0xa6, 0xc8, 0xc6, 0xcd, 0x8a, 0x8f, 0x7c, 0x5d, 0x51, 0xc8, 0xfa, 0x6f,
-+    0xb3, 0x93, 0xdb, 0x71, 0xef, 0x3e, 0x6e, 0xa7, 0x85, 0xc7, 0xd4, 0x3e,
-+    0xa2, 0xe2, 0xc0, 0xaa, 0x17, 0xb3, 0xa4, 0x7c, 0xc2, 0x3f, 0x7c, 0x7a,
-+    0xdd, 0x26, 0xde, 0x3e, 0xf1, 0x99, 0x06, 0xf7, 0x69, 0x1b, 0xc9, 0x20,
-+    0x55, 0x4f, 0x86, 0x7a, 0x93, 0x89, 0x68, 0xe9, 0x2b, 0x2d, 0xbc, 0x08,
-+    0x15, 0x5d, 0x2d, 0x0b, 0x4f, 0x1a, 0xb3, 0xd4, 0x8e, 0x77, 0x79, 0x2a,
-+    0x25, 0xf9, 0xb6, 0x46, 0xfb, 0x87, 0x02, 0xa6, 0xe0, 0xd3, 0xba, 0x84,
-+    0xea, 0x3e, 0x58, 0xa5, 0x7f, 0x8f, 0x8c, 0x39, 0x79, 0x28, 0xb5, 0xcf,
-+    0xe4, 0xca, 0x63, 0xdc, 0xac, 0xed, 0x4b, 0x74, 0x1e, 0x94, 0x85, 0x8c,
-+    0xe5, 0xf4, 0x76, 0x6f, 0x20, 0x67, 0x8b, 0xd8, 0xd6, 0x4b, 0xe7, 0x2d,
-+    0xa0, 0xbd, 0xcc, 0x1f, 0xdf, 0x46, 0x9c, 0xa2, 0x49, 0x64, 0xdf, 0x24,
-+    0x00, 0x11, 0x11, 0x45, 0x62, 0x5c, 0xd7, 0x8a, 0x00, 0x02, 0xf5, 0x9b,
-+    0x4f, 0x53, 0x42, 0xc5, 0xd5, 0x55, 0x80, 0x73, 0x9a, 0x5b, 0x31, 0x5a,
-+    0xbd, 0x3a, 0x43, 0xe9, 0x33, 0xe5, 0xaf, 0x1d, 0x92, 0x5e, 0x59, 0x37,
-+    0xae, 0x57, 0xfa, 0x3b, 0xd2, 0x31, 0xae, 0xa6, 0xf9, 0xc9, 0xc1, 0x82,
-+    0xa6, 0xa5, 0xed, 0x24, 0x53, 0x4b, 0x38, 0x22, 0xf2, 0x85, 0x8d, 0x13,
-+    0xa6, 0x5e, 0xd6, 0x57, 0x17, 0xd3, 0x33, 0x38, 0x8d, 0x65, 0xd3, 0xcb,
-+    0x1a, 0xa2, 0x3a, 0x2b, 0xbb, 0x61, 0x53, 0xd7, 0xff, 0xcd, 0x20, 0xb6,
-+    0xbb, 0x8c, 0xab, 0x63, 0xef, 0xb8, 0x26, 0x7e, 0x81, 0x65, 0xaf, 0x90,
-+    0xfc, 0xd2, 0xb6, 0x72, 0xdb, 0xe9, 0x23, 0x78, 0x12, 0x04, 0xc0, 0x03,
-+    0x82, 0xa8, 0x7a, 0x0f, 0x48, 0x6f, 0x82, 0x7f, 0x81, 0xcd, 0xa7, 0x89,
-+    0xdd, 0x86, 0xea, 0x5e, 0xa1, 0x50, 0x14, 0x34, 0x17, 0x64, 0x82, 0x0f,
-+    0xc4, 0x40, 0x20, 0x1d, 0x8f, 0xfe, 0xfa, 0x99, 0xaf, 0x5b, 0xc1, 0x5d,
-+    0xc8, 0x47, 0x07, 0x54, 0x4a, 0x22, 0x56, 0x57, 0xf1, 0x2c, 0x3b, 0x62,
-+    0x7f, 0x12, 0x62, 0xaf, 0xfd, 0xf8, 0x04, 0x11, 0xa8, 0x51, 0xf0, 0x46,
-+    0x5d, 0x79, 0x66, 0xff, 0x8a, 0x06, 0xef, 0x54, 0x64, 0x1b, 0x84, 0x3e,
-+    0x41, 0xf3, 0xfe, 0x19, 0x51, 0xf7, 0x44, 0x9c, 0x16, 0xd3, 0x7a, 0x09,
-+    0x59, 0xf5, 0x47, 0x45, 0xd0, 0x31, 0xef, 0x96, 0x2c, 0xc5, 0xc0, 0xd0,
-+    0x56, 0xef, 0x3f, 0x07, 0x2b, 0xb7, 0x28, 0x49, 0xf5, 0xb1, 0x42, 0x18,
-+    0xcf, 0x77, 0xd8, 0x2b, 0x71, 0x74, 0x80, 0xba, 0x34, 0x52, 0xce, 0x11,
-+    0xfe, 0xc4, 0xb9, 0xeb, 0xf9, 0xc4, 0x5e, 0x1f, 0xd3, 0xde, 0x4b, 0x14,
-+    0xe3, 0x6e, 0xe7, 0xd7, 0x83, 0x59, 0x98, 0xe8, 0x3d, 0x8e, 0xd6, 0x7d,
-+    0xc0, 0x9a, 0x79, 0xb9, 0x83, 0xf1, 0xc1, 0x00, 0x5d, 0x16, 0x1b, 0x44,
-+    0xe9, 0x02, 0xce, 0x99, 0x1e, 0x77, 0xef, 0xca, 0xbc, 0xf0, 0x6a, 0xb9,
-+    0x65, 0x3f, 0x3c, 0xd9, 0xe1, 0x63, 0x0b, 0xbf, 0xaa, 0xa7, 0xe6, 0x6d,
-+    0x6d, 0x3f, 0x44, 0x29, 0xa3, 0x8b, 0x6d, 0xc4, 0x81, 0xa9, 0xc3, 0x5a,
-+    0x90, 0x55, 0x72, 0x61, 0x17, 0x22, 0x7f, 0x3e, 0x5f, 0xfc, 0xba, 0xb3,
-+    0x7a, 0x99, 0x76, 0xe9, 0x20, 0xe5, 0xc5, 0xe8, 0x55, 0x56, 0x0f, 0x7a,
-+    0x48, 0xe7, 0xbc, 0xe1, 0x13, 0xf4, 0x90, 0xef, 0x97, 0x6c, 0x02, 0x89,
-+    0x4d, 0x22, 0x48, 0xda, 0xd3, 0x52, 0x45, 0x31, 0x26, 0xcc, 0xe8, 0x9e,
-+    0x5d, 0xdd, 0x75, 0xe4, 0x1d, 0xbc, 0xb1, 0x08, 0x55, 0xaf, 0x54, 0x70,
-+    0x0d, 0x0c, 0xf3, 0x50, 0xbc, 0x40, 0x83, 0xee, 0xdc, 0x6d, 0x8b, 0x40,
-+    0x79, 0x62, 0x18, 0x37, 0xc4, 0x78, 0x02, 0x58, 0x7c, 0x78, 0xd3, 0x54,
-+    0xed, 0x31, 0xbd, 0x7d, 0x48, 0xcf, 0xb6, 0x11, 0x27, 0x37, 0x9c, 0x86,
-+    0xf7, 0x2e, 0x00, 0x7a, 0x48, 0x1b, 0xa6, 0x72, 0x70, 0x7b, 0x44, 0x45,
-+    0xeb, 0x49, 0xbf, 0xbe, 0x09, 0x78, 0x66, 0x71, 0x12, 0x7f, 0x3d, 0x78,
-+    0x51, 0x24, 0x82, 0xa2, 0xf0, 0x1e, 0x83, 0x81, 0x81, 0x45, 0x53, 0xfd,
-+    0x5e, 0xf3, 0x03, 0x74, 0xbd, 0x23, 0x35, 0xf6, 0x10, 0xdd, 0x7c, 0x73,
-+    0x46, 0x32, 0x09, 0x54, 0x99, 0x95, 0x91, 0x25, 0xb8, 0x32, 0x09, 0xd8,
-+    0x2f, 0x97, 0x50, 0xa3, 0xf5, 0xd6, 0xb1, 0xed, 0x97, 0x51, 0x06, 0x42,
-+    0x12, 0x0c, 0x69, 0x38, 0x09, 0xa0, 0xd8, 0x19, 0x70, 0xf7, 0x8f, 0x61,
-+    0x0d, 0x56, 0x43, 0x66, 0x22, 0x8b, 0x0e, 0x0e, 0xf9, 0x81, 0x9f, 0xac,
-+    0x6f, 0xbf, 0x7d, 0x04, 0x13, 0xf2, 0xe4, 0xeb, 0xfd, 0xbe, 0x4e, 0x56,
-+    0xda, 0xe0, 0x22, 0x6d, 0x1b, 0x25, 0xc8, 0xa5, 0x9c, 0x05, 0x45, 0x52,
-+    0x3c, 0x3a, 0xde, 0x6b, 0xac, 0x9b, 0xf8, 0x81, 0x97, 0x21, 0x46, 0xac,
-+    0x7e, 0x89, 0xf8, 0x49, 0x58, 0xbb, 0x45, 0xac, 0xa2, 0xc4, 0x90, 0x1f,
-+    0xb2, 0xb4, 0xf8, 0xe0, 0xcd, 0xa1, 0x9d, 0x1c, 0xf2, 0xf1, 0xdf, 0xfb,
-+    0x88, 0x4e, 0xe5, 0x41, 0xd8, 0x6e, 0xac, 0x07, 0x87, 0x95, 0x35, 0xa6,
-+    0x12, 0x08, 0x5d, 0x57, 0x5e, 0xaf, 0x71, 0x0f, 0x07, 0x4e, 0x81, 0x77,
-+    0xf1, 0xef, 0xb5, 0x35, 0x5c, 0xfa, 0xf4, 0x4e, 0x42, 0xdc, 0x19, 0xfe,
-+    0xe4, 0xd2, 0xb4, 0x27, 0xfb, 0x34, 0x1f, 0xb2, 0x6f, 0xf2, 0x95, 0xcc,
-+    0xd4, 0x47, 0x63, 0xdc, 0x7e, 0x4f, 0x97, 0x2b, 0x7a, 0xe0, 0x80, 0x31,
-+};
-+
-+static const uint8_t kSpakeMSmallPrecomp[15 * 2 * 32] = {
-+    0xe7, 0x45, 0x7e, 0x47, 0x49, 0x69, 0xbd, 0x1b, 0x35, 0x1c, 0x2c, 0x98,
-+    0x03, 0xf3, 0xb3, 0x37, 0xde, 0x39, 0xa5, 0xda, 0xc0, 0x2e, 0xa4, 0xac,
-+    0x7d, 0x08, 0x26, 0xfc, 0x80, 0xa7, 0x09, 0x12, 0xd0, 0x48, 0x03, 0x2c,
-+    0x6e, 0xa0, 0xb6, 0xd6, 0x97, 0xdd, 0xc2, 0xe8, 0x6b, 0xda, 0x85, 0xa3,
-+    0x3a, 0xda, 0xc9, 0x20, 0xf1, 0xbf, 0x18, 0xe1, 0xb0, 0xc6, 0xd1, 0x66,
-+    0xa5, 0xce, 0xcd, 0x2f, 0x80, 0xa8, 0x4e, 0xc3, 0x81, 0xae, 0x68, 0x3b,
-+    0x0d, 0xdb, 0x56, 0x32, 0x2f, 0xa8, 0x97, 0xa0, 0x5c, 0x15, 0xc1, 0xcb,
-+    0x6f, 0x7a, 0x5f, 0xc5, 0x32, 0xfb, 0x49, 0x17, 0x18, 0xfa, 0x85, 0x08,
-+    0x85, 0xf1, 0xe3, 0x11, 0x8e, 0x3d, 0x70, 0x20, 0x38, 0x4e, 0x0c, 0x17,
-+    0xa1, 0xa8, 0x20, 0xd2, 0xb1, 0x1d, 0x05, 0x8d, 0x0f, 0xc9, 0x96, 0x18,
-+    0x9d, 0x8c, 0x89, 0x8f, 0x46, 0x6a, 0x6c, 0x6e, 0x72, 0x03, 0xb2, 0x75,
-+    0x87, 0xd8, 0xa9, 0x60, 0x93, 0x2b, 0x8b, 0x66, 0xee, 0xaf, 0xce, 0x98,
-+    0xcd, 0x6b, 0x7c, 0x6a, 0xbe, 0x19, 0xda, 0x66, 0x7c, 0xda, 0x53, 0xa0,
-+    0xe3, 0x9a, 0x0e, 0x53, 0x3a, 0x7c, 0x73, 0x4a, 0x37, 0xa6, 0x53, 0x23,
-+    0x67, 0x31, 0xce, 0x8a, 0xab, 0xee, 0x72, 0x76, 0xc2, 0xb5, 0x54, 0x42,
-+    0xcf, 0x4b, 0xc7, 0x53, 0x24, 0x59, 0xaf, 0x76, 0x53, 0x10, 0x7e, 0x25,
-+    0x94, 0x5c, 0x23, 0xa6, 0x5e, 0x05, 0xea, 0x14, 0xad, 0x2b, 0xce, 0x50,
-+    0x77, 0xb3, 0x7a, 0x88, 0x4c, 0xf7, 0x74, 0x04, 0x35, 0xa4, 0x0c, 0x9e,
-+    0xee, 0x6a, 0x4c, 0x3c, 0xc1, 0x6a, 0x35, 0x4d, 0x6d, 0x8f, 0x94, 0x95,
-+    0xe4, 0x10, 0xca, 0x46, 0x4e, 0xfa, 0x38, 0x40, 0xeb, 0x1a, 0x1b, 0x5a,
-+    0xff, 0x73, 0x4d, 0xe9, 0xf2, 0xbe, 0x89, 0xf5, 0xd1, 0x72, 0xd0, 0x1a,
-+    0x7b, 0x82, 0x08, 0x19, 0xda, 0x54, 0x44, 0xa5, 0x3d, 0xd8, 0x10, 0x1c,
-+    0xcf, 0x3b, 0xc7, 0x54, 0xd5, 0x11, 0xd7, 0x2a, 0x69, 0x3f, 0xa6, 0x58,
-+    0x74, 0xfd, 0x90, 0xb2, 0xf4, 0xc2, 0x0e, 0xf3, 0x19, 0x8f, 0x51, 0x7c,
-+    0x31, 0x12, 0x79, 0x61, 0x16, 0xb4, 0x2f, 0x2f, 0xd0, 0x88, 0x97, 0xf2,
-+    0xc3, 0x8c, 0xa6, 0xa3, 0x29, 0xff, 0x7e, 0x12, 0x46, 0x2a, 0x9c, 0x09,
-+    0x7c, 0x5f, 0x87, 0x07, 0x6b, 0xa1, 0x9a, 0x57, 0x55, 0x8e, 0xb0, 0x56,
-+    0x5d, 0xc9, 0x4c, 0x5b, 0xae, 0xd3, 0xd0, 0x8e, 0xb8, 0xac, 0xba, 0xe8,
-+    0x54, 0x45, 0x30, 0x14, 0xf6, 0x59, 0x20, 0xc4, 0x03, 0xb7, 0x7a, 0x5d,
-+    0x6b, 0x5a, 0xcb, 0x28, 0x60, 0xf8, 0xef, 0x61, 0x60, 0x78, 0x6b, 0xf5,
-+    0x21, 0x4b, 0x75, 0xc2, 0x77, 0xba, 0x0e, 0x38, 0x98, 0xe0, 0xfb, 0xb7,
-+    0x5f, 0x75, 0x87, 0x04, 0x0c, 0xb4, 0x5c, 0x09, 0x04, 0x00, 0x38, 0x4e,
-+    0x4f, 0x7b, 0x73, 0xe5, 0xdb, 0xdb, 0xf1, 0xf4, 0x5c, 0x64, 0x68, 0xfd,
-+    0xb1, 0x86, 0xe8, 0x89, 0xbe, 0x9c, 0xd4, 0x96, 0x1d, 0xcb, 0xdc, 0x5c,
-+    0xef, 0xd4, 0x33, 0x28, 0xb9, 0xb6, 0xaf, 0x3b, 0xcf, 0x8d, 0x30, 0xba,
-+    0xe8, 0x08, 0xcf, 0x84, 0xba, 0x61, 0x10, 0x9b, 0x62, 0xf6, 0x18, 0x79,
-+    0x66, 0x87, 0x82, 0x7c, 0xaa, 0x71, 0xac, 0xd0, 0xd0, 0x32, 0xb0, 0x54,
-+    0x03, 0xa4, 0xad, 0x3f, 0x72, 0xca, 0x22, 0xff, 0x01, 0x87, 0x08, 0x36,
-+    0x61, 0x22, 0xaa, 0x18, 0xab, 0x3a, 0xbc, 0xf2, 0x78, 0x05, 0xe1, 0x99,
-+    0xa3, 0x59, 0x98, 0xcc, 0x21, 0xc6, 0x2b, 0x51, 0x6d, 0x43, 0x0a, 0x46,
-+    0x50, 0xae, 0x11, 0x7e, 0xd5, 0x23, 0x56, 0xef, 0x83, 0xc8, 0xbf, 0x42,
-+    0xf0, 0x45, 0x52, 0x1f, 0x34, 0xbc, 0x2f, 0xb0, 0xf0, 0xce, 0xf0, 0xec,
-+    0xd0, 0x99, 0x59, 0x2e, 0x1f, 0xab, 0xa8, 0x1e, 0x4b, 0xce, 0x1b, 0x9a,
-+    0x75, 0xc6, 0xc4, 0x71, 0x86, 0xf0, 0x8d, 0xec, 0xb0, 0x30, 0xb9, 0x62,
-+    0xb3, 0xb7, 0xdd, 0x96, 0x29, 0xc8, 0xbf, 0xe9, 0xb0, 0x74, 0x78, 0x7b,
-+    0xf7, 0xea, 0xa3, 0x14, 0x12, 0x56, 0xe0, 0xf3, 0x35, 0x7a, 0x26, 0x4a,
-+    0x4c, 0xe6, 0xdf, 0x13, 0xb5, 0x52, 0xb0, 0x2a, 0x5f, 0x2e, 0xac, 0x34,
-+    0xab, 0x5f, 0x1a, 0x01, 0xe4, 0x15, 0x1a, 0xd1, 0xbf, 0xc9, 0x95, 0x0a,
-+    0xac, 0x1d, 0xe7, 0x53, 0x59, 0x8d, 0xc3, 0x21, 0x78, 0x5e, 0x12, 0x97,
-+    0x8f, 0x4e, 0x1d, 0xf9, 0xe5, 0xe2, 0xc2, 0xc4, 0xba, 0xfb, 0x50, 0x96,
-+    0x5b, 0x43, 0xe8, 0xf7, 0x0d, 0x1b, 0x64, 0x58, 0xbe, 0xd3, 0x95, 0x7f,
-+    0x8e, 0xf1, 0x85, 0x35, 0xba, 0x25, 0x55, 0x2e, 0x02, 0x46, 0x5c, 0xad,
-+    0x1f, 0xc5, 0x03, 0xcc, 0xd0, 0x43, 0x4c, 0xf2, 0x5e, 0x64, 0x0a, 0x89,
-+    0xd9, 0xfd, 0x23, 0x7d, 0x4f, 0xbe, 0x2f, 0x0f, 0x1e, 0x12, 0x4a, 0xd9,
-+    0xf8, 0x82, 0xde, 0x8f, 0x4f, 0x98, 0xb9, 0x90, 0xf6, 0xfa, 0xd1, 0x11,
-+    0xa6, 0xdc, 0x7e, 0x32, 0x48, 0x6a, 0x8a, 0x14, 0x5e, 0x73, 0xb9, 0x6c,
-+    0x0e, 0xc2, 0xf9, 0xcc, 0xf0, 0x32, 0xc8, 0xb5, 0x56, 0xaa, 0x5d, 0xd2,
-+    0x07, 0xf1, 0x6f, 0x33, 0x6f, 0x05, 0x70, 0x49, 0x60, 0x49, 0x23, 0x23,
-+    0x14, 0x0e, 0x4c, 0x58, 0x92, 0xad, 0xa9, 0x50, 0xb1, 0x59, 0x43, 0x96,
-+    0x7b, 0xc1, 0x51, 0x45, 0xef, 0x0d, 0xef, 0xd1, 0xe4, 0xd0, 0xce, 0xdf,
-+    0x6a, 0xbc, 0x1b, 0xbf, 0x7a, 0x87, 0x4e, 0x47, 0x17, 0x9c, 0x34, 0x38,
-+    0xb0, 0x3c, 0xa1, 0x04, 0xfb, 0xe2, 0x66, 0xce, 0xb6, 0x82, 0xbb, 0xad,
-+    0xc3, 0x8e, 0x12, 0x35, 0xbc, 0x17, 0xce, 0x01, 0x2d, 0xa3, 0xa6, 0xb9,
-+    0xfa, 0x84, 0xc2, 0x2f, 0x5a, 0x4a, 0x8c, 0x4c, 0x11, 0x4e, 0xa8, 0x14,
-+    0xcb, 0xb8, 0x99, 0xaa, 0x2e, 0x8c, 0xa0, 0xc9, 0x5f, 0x62, 0x2a, 0x84,
-+    0x66, 0x60, 0x0a, 0x7e, 0xdc, 0x93, 0x17, 0x45, 0x19, 0xb3, 0x93, 0x4c,
-+    0xdc, 0xd0, 0xd5, 0x5c, 0x25, 0xd2, 0xcd, 0x4e, 0x84, 0x4c, 0x73, 0xb3,
-+    0x90, 0xa4, 0x22, 0x05, 0x2c, 0x7c, 0x39, 0x2b, 0x70, 0xd9, 0x61, 0x76,
-+    0xb2, 0x03, 0x71, 0xe9, 0x0e, 0xf8, 0x57, 0x85, 0xad, 0xb1, 0x2f, 0x34,
-+    0xa5, 0x66, 0xb0, 0x0f, 0x75, 0x94, 0x6e, 0x26, 0x79, 0x99, 0xb4, 0xe2,
-+    0xe2, 0xa3, 0x58, 0xdd, 0xb4, 0xfb, 0x74, 0xf4, 0xa1, 0xca, 0xc3, 0x30,
-+    0xe7, 0x86, 0xb2, 0xa2, 0x2c, 0x11, 0xc9, 0x58, 0xe3, 0xc1, 0xa6, 0x5f,
-+    0x86, 0x6a, 0xe7, 0x75, 0xd5, 0xd8, 0x63, 0x95, 0x64, 0x59, 0xbc, 0xb8,
-+    0xb7, 0xf5, 0x12, 0xe3, 0x03, 0xc6, 0x17, 0xea, 0x4e, 0xcb, 0xee, 0x4c,
-+    0xae, 0x03, 0xd1, 0x33, 0xd0, 0x39, 0x36, 0x00, 0x0f, 0xf4, 0x9c, 0xbd,
-+    0x35, 0x96, 0xfd, 0x0d, 0x26, 0xb7, 0x9e, 0xf4, 0x4b, 0x6f, 0x4b, 0xf1,
-+    0xec, 0x11, 0x00, 0x16, 0x21, 0x1e, 0xd4, 0x43, 0x23, 0x8c, 0x4a, 0xfa,
-+    0x9e, 0xd4, 0x2b, 0x36, 0x9a, 0x43, 0x1e, 0x58, 0x31, 0xe8, 0x1f, 0x83,
-+    0x15, 0x20, 0x31, 0x68, 0xfe, 0x27, 0xd3, 0xd8, 0x9b, 0x43, 0x81, 0x8f,
-+    0x57, 0x32, 0x14, 0xe6, 0x9e, 0xbf, 0xd1, 0xfb, 0xdf, 0xad, 0x7a, 0x52,
-+};
-+
-+/* left_shift_3 sets |n| to |n|*8, where |n| is represented in little-endian
-+ * order. */
-+static void left_shift_3(uint8_t n[32]) {
-+  uint8_t carry = 0;
-+  unsigned i;
-+
-+  for (i = 0; i < 32; i++) {
-+    const uint8_t next_carry = n[i] >> 5;
-+    n[i] = (n[i] << 3) | carry;
-+    carry = next_carry;
-+  }
-+}
-+
-+static krb5_error_code
-+builtin_edwards25519_keygen(krb5_context context, groupdata *gdata,
-+                            const uint8_t *wbytes, krb5_boolean use_m,
-+                            uint8_t *priv_out, uint8_t *pub_out)
-+{
-+  uint8_t private[64];
-+  krb5_data data = make_data(private, 32);
-+  krb5_error_code ret;
-+
-+  /* Pick x or y uniformly from [0, p*h) divisible by h. */
-+  ret = krb5_c_random_make_octets(context, &data);
-+  if (ret)
-+    return ret;
-+  memset(private + 32, 0, 32);
-+  x25519_sc_reduce(private);
-+  left_shift_3(private);
-+
-+  /* Compute X=x*G or Y=y*G. */
-+  ge_p3 P;
-+  x25519_ge_scalarmult_base(&P, private);
-+
-+  /* Compute w mod p. */
-+  uint8_t wreduced[64];
-+  memcpy(wreduced, wbytes, 32);
-+  memset(wreduced + 32, 0, 32);
-+  x25519_sc_reduce(wreduced);
-+
-+  /* Compute the mask, w*M or w*N. */
-+  ge_p3 mask;
-+  x25519_ge_scalarmult_small_precomp(&mask, wreduced,
-+                                     use_m ? kSpakeMSmallPrecomp :
-+                                     kSpakeNSmallPrecomp);
-+
-+  /* Compute the masked point T=w*M+X or S=w*N+Y. */
-+  ge_cached mask_cached;
-+  x25519_ge_p3_to_cached(&mask_cached, &mask);
-+  ge_p1p1 Pmasked;
-+  x25519_ge_add(&Pmasked, &P, &mask_cached);
-+
-+  /* Encode T or S into pub_out. */
-+  ge_p2 Pmasked_proj;
-+  x25519_ge_p1p1_to_p2(&Pmasked_proj, &Pmasked);
-+  x25519_ge_tobytes(pub_out, &Pmasked_proj);
-+
-+  /* Remember the private key in priv_out. */
-+  memcpy(priv_out, private, 32);
-+  return 0;
-+}
-+
-+static krb5_error_code
-+builtin_edwards25519_result(krb5_context context, groupdata *gdata,
-+                            const uint8_t *wbytes, const uint8_t *ourpriv,
-+                            const uint8_t *theirpub, krb5_boolean use_m,
-+                            uint8_t *elem_out)
-+{
-+  /*
-+   * Check if the point received from peer is on the curve.  This does not
-+   * verify that it is in the generator subgroup, but since our private key is
-+   * a multiple of the cofactor, the shared point will be in the generator
-+   * subgroup even if a rogue peer sends a point which is not.
-+   */
-+  ge_p3 Qmasked;
-+  if (x25519_ge_frombytes_vartime(&Qmasked, theirpub) != 0)
-+    return EINVAL;
-+
-+  /* Compute w mod p. */
-+  uint8_t wreduced[64];
-+  memcpy(wreduced, wbytes, 32);
-+  memset(wreduced + 32, 0, 32);
-+  x25519_sc_reduce(wreduced);
-+
-+  /* Compute the peer's mask, w*M or w*N. */
-+  ge_p3 peers_mask;
-+  x25519_ge_scalarmult_small_precomp(&peers_mask, wreduced,
-+                                     use_m ? kSpakeMSmallPrecomp :
-+                                     kSpakeNSmallPrecomp);
-+
-+  ge_cached peers_mask_cached;
-+  x25519_ge_p3_to_cached(&peers_mask_cached, &peers_mask);
-+
-+  /* Compute the peer's unmasked point, T-w*M or S-w*N. */
-+  ge_p1p1 Qcompl;
-+  ge_p3 Qunmasked;
-+  x25519_ge_sub(&Qcompl, &Qmasked, &peers_mask_cached);
-+  x25519_ge_p1p1_to_p3(&Qunmasked, &Qcompl);
-+
-+  /* Multiply by our private value to compute K=x*(S-w*N) or K=y*(T-w*M). */
-+  ge_p2 K;
-+  x25519_ge_scalarmult(&K, ourpriv, &Qunmasked);
-+
-+  /* Encode K into elem_out. */
-+  x25519_ge_tobytes(elem_out, &K);
-+  return 0;
-+}
-+
-+static krb5_error_code
-+builtin_sha256(krb5_context context, groupdata *gdata, const krb5_data *dlist,
-+               size_t ndata, uint8_t *result_out)
-+{
-+  return k5_sha256(dlist, ndata, result_out);
-+}
-+
-+groupdef builtin_edwards25519 = {
-+  .reg = &spake_iana_edwards25519,
-+  .keygen = builtin_edwards25519_keygen,
-+  .result = builtin_edwards25519_result,
-+  .hash = builtin_sha256
-+};
-diff --git a/src/plugins/preauth/spake/edwards25519_tables.h b/src/plugins/preauth/spake/edwards25519_tables.h
-new file mode 100644
-index 000000000..c6c501373
---- /dev/null
-+++ b/src/plugins/preauth/spake/edwards25519_tables.h
-@@ -0,0 +1,7881 @@
-+/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-+/*
-+ * The MIT License (MIT)
-+ *
-+ * Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file).
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this software and associated documentation files (the "Software"), to deal
-+ * in the Software without restriction, including without limitation the rights
-+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-+ * copies of the Software, and to permit persons to whom the Software is
-+ * furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-+ * SOFTWARE.
-+ */
-+
-+/* From BoringSSL third-party/fiat/curve25519_tables.h */
-+
-+static const fe d = {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+    929955233495203, 466365720129213, 1662059464998953, 2033849074728123,
-+    1442794654840575
-+#else
-+    56195235, 13857412, 51736253, 6949390, 114729, 24766616, 60832955, 30306712,
-+    48412415, 21499315
-+#endif
-+}};
-+
-+static const fe sqrtm1 = {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+    1718705420411056, 234908883556509, 2233514472574048, 2117202627021982,
-+    765476049583133
-+#else
-+    34513072, 25610706, 9377949, 3500415, 12389472, 33281959, 41962654,
-+    31548777, 326685, 11406482
-+#endif
-+}};
-+
-+static const fe d2 = {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+    1859910466990425, 932731440258426, 1072319116312658, 1815898335770999,
-+    633789495995903
-+#else
-+    45281625, 27714825, 36363642, 13898781, 229458, 15978800, 54557047,
-+    27058993, 29715967, 9444199
-+#endif
-+}};
-+
-+#if defined(CONFIG_SMALL)
-+
-+// This block of code replaces the standard base-point table with a much smaller
-+// one. The standard table is 30,720 bytes while this one is just 960.
-+//
-+// This table contains 15 pairs of group elements, (x, y), where each field
-+// element is serialised with |fe_tobytes|. If |i| is the index of the group
-+// element then consider i+1 as a four-bit number: (i₀, i₁, i₂, i₃) (where i₀
-+// is the most significant bit). The value of the group element is then:
-+// (i₀×2^192 + i₁×2^128 + i₂×2^64 + i₃)G, where G is the generator.
-+static const uint8_t k25519SmallPrecomp[15 * 2 * 32] = {
-+    0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
-+    0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
-+    0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21, 0x58, 0x66, 0x66, 0x66,
-+    0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
-+    0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
-+    0x66, 0x66, 0x66, 0x66, 0x02, 0xa2, 0xed, 0xf4, 0x8f, 0x6b, 0x0b, 0x3e,
-+    0xeb, 0x35, 0x1a, 0xd5, 0x7e, 0xdb, 0x78, 0x00, 0x96, 0x8a, 0xa0, 0xb4,
-+    0xcf, 0x60, 0x4b, 0xd4, 0xd5, 0xf9, 0x2d, 0xbf, 0x88, 0xbd, 0x22, 0x62,
-+    0x13, 0x53, 0xe4, 0x82, 0x57, 0xfa, 0x1e, 0x8f, 0x06, 0x2b, 0x90, 0xba,
-+    0x08, 0xb6, 0x10, 0x54, 0x4f, 0x7c, 0x1b, 0x26, 0xed, 0xda, 0x6b, 0xdd,
-+    0x25, 0xd0, 0x4e, 0xea, 0x42, 0xbb, 0x25, 0x03, 0xa2, 0xfb, 0xcc, 0x61,
-+    0x67, 0x06, 0x70, 0x1a, 0xc4, 0x78, 0x3a, 0xff, 0x32, 0x62, 0xdd, 0x2c,
-+    0xab, 0x50, 0x19, 0x3b, 0xf2, 0x9b, 0x7d, 0xb8, 0xfd, 0x4f, 0x29, 0x9c,
-+    0xa7, 0x91, 0xba, 0x0e, 0x46, 0x5e, 0x51, 0xfe, 0x1d, 0xbf, 0xe5, 0xe5,
-+    0x9b, 0x95, 0x0d, 0x67, 0xf8, 0xd1, 0xb5, 0x5a, 0xa1, 0x93, 0x2c, 0xc3,
-+    0xde, 0x0e, 0x97, 0x85, 0x2d, 0x7f, 0xea, 0xab, 0x3e, 0x47, 0x30, 0x18,
-+    0x24, 0xe8, 0xb7, 0x60, 0xae, 0x47, 0x80, 0xfc, 0xe5, 0x23, 0xe7, 0xc2,
-+    0xc9, 0x85, 0xe6, 0x98, 0xa0, 0x29, 0x4e, 0xe1, 0x84, 0x39, 0x2d, 0x95,
-+    0x2c, 0xf3, 0x45, 0x3c, 0xff, 0xaf, 0x27, 0x4c, 0x6b, 0xa6, 0xf5, 0x4b,
-+    0x11, 0xbd, 0xba, 0x5b, 0x9e, 0xc4, 0xa4, 0x51, 0x1e, 0xbe, 0xd0, 0x90,
-+    0x3a, 0x9c, 0xc2, 0x26, 0xb6, 0x1e, 0xf1, 0x95, 0x7d, 0xc8, 0x6d, 0x52,
-+    0xe6, 0x99, 0x2c, 0x5f, 0x9a, 0x96, 0x0c, 0x68, 0x29, 0xfd, 0xe2, 0xfb,
-+    0xe6, 0xbc, 0xec, 0x31, 0x08, 0xec, 0xe6, 0xb0, 0x53, 0x60, 0xc3, 0x8c,
-+    0xbe, 0xc1, 0xb3, 0x8a, 0x8f, 0xe4, 0x88, 0x2b, 0x55, 0xe5, 0x64, 0x6e,
-+    0x9b, 0xd0, 0xaf, 0x7b, 0x64, 0x2a, 0x35, 0x25, 0x10, 0x52, 0xc5, 0x9e,
-+    0x58, 0x11, 0x39, 0x36, 0x45, 0x51, 0xb8, 0x39, 0x93, 0xfc, 0x9d, 0x6a,
-+    0xbe, 0x58, 0xcb, 0xa4, 0x0f, 0x51, 0x3c, 0x38, 0x05, 0xca, 0xab, 0x43,
-+    0x63, 0x0e, 0xf3, 0x8b, 0x41, 0xa6, 0xf8, 0x9b, 0x53, 0x70, 0x80, 0x53,
-+    0x86, 0x5e, 0x8f, 0xe3, 0xc3, 0x0d, 0x18, 0xc8, 0x4b, 0x34, 0x1f, 0xd8,
-+    0x1d, 0xbc, 0xf2, 0x6d, 0x34, 0x3a, 0xbe, 0xdf, 0xd9, 0xf6, 0xf3, 0x89,
-+    0xa1, 0xe1, 0x94, 0x9f, 0x5d, 0x4c, 0x5d, 0xe9, 0xa1, 0x49, 0x92, 0xef,
-+    0x0e, 0x53, 0x81, 0x89, 0x58, 0x87, 0xa6, 0x37, 0xf1, 0xdd, 0x62, 0x60,
-+    0x63, 0x5a, 0x9d, 0x1b, 0x8c, 0xc6, 0x7d, 0x52, 0xea, 0x70, 0x09, 0x6a,
-+    0xe1, 0x32, 0xf3, 0x73, 0x21, 0x1f, 0x07, 0x7b, 0x7c, 0x9b, 0x49, 0xd8,
-+    0xc0, 0xf3, 0x25, 0x72, 0x6f, 0x9d, 0xed, 0x31, 0x67, 0x36, 0x36, 0x54,
-+    0x40, 0x92, 0x71, 0xe6, 0x11, 0x28, 0x11, 0xad, 0x93, 0x32, 0x85, 0x7b,
-+    0x3e, 0xb7, 0x3b, 0x49, 0x13, 0x1c, 0x07, 0xb0, 0x2e, 0x93, 0xaa, 0xfd,
-+    0xfd, 0x28, 0x47, 0x3d, 0x8d, 0xd2, 0xda, 0xc7, 0x44, 0xd6, 0x7a, 0xdb,
-+    0x26, 0x7d, 0x1d, 0xb8, 0xe1, 0xde, 0x9d, 0x7a, 0x7d, 0x17, 0x7e, 0x1c,
-+    0x37, 0x04, 0x8d, 0x2d, 0x7c, 0x5e, 0x18, 0x38, 0x1e, 0xaf, 0xc7, 0x1b,
-+    0x33, 0x48, 0x31, 0x00, 0x59, 0xf6, 0xf2, 0xca, 0x0f, 0x27, 0x1b, 0x63,
-+    0x12, 0x7e, 0x02, 0x1d, 0x49, 0xc0, 0x5d, 0x79, 0x87, 0xef, 0x5e, 0x7a,
-+    0x2f, 0x1f, 0x66, 0x55, 0xd8, 0x09, 0xd9, 0x61, 0x38, 0x68, 0xb0, 0x07,
-+    0xa3, 0xfc, 0xcc, 0x85, 0x10, 0x7f, 0x4c, 0x65, 0x65, 0xb3, 0xfa, 0xfa,
-+    0xa5, 0x53, 0x6f, 0xdb, 0x74, 0x4c, 0x56, 0x46, 0x03, 0xe2, 0xd5, 0x7a,
-+    0x29, 0x1c, 0xc6, 0x02, 0xbc, 0x59, 0xf2, 0x04, 0x75, 0x63, 0xc0, 0x84,
-+    0x2f, 0x60, 0x1c, 0x67, 0x76, 0xfd, 0x63, 0x86, 0xf3, 0xfa, 0xbf, 0xdc,
-+    0xd2, 0x2d, 0x90, 0x91, 0xbd, 0x33, 0xa9, 0xe5, 0x66, 0x0c, 0xda, 0x42,
-+    0x27, 0xca, 0xf4, 0x66, 0xc2, 0xec, 0x92, 0x14, 0x57, 0x06, 0x63, 0xd0,
-+    0x4d, 0x15, 0x06, 0xeb, 0x69, 0x58, 0x4f, 0x77, 0xc5, 0x8b, 0xc7, 0xf0,
-+    0x8e, 0xed, 0x64, 0xa0, 0xb3, 0x3c, 0x66, 0x71, 0xc6, 0x2d, 0xda, 0x0a,
-+    0x0d, 0xfe, 0x70, 0x27, 0x64, 0xf8, 0x27, 0xfa, 0xf6, 0x5f, 0x30, 0xa5,
-+    0x0d, 0x6c, 0xda, 0xf2, 0x62, 0x5e, 0x78, 0x47, 0xd3, 0x66, 0x00, 0x1c,
-+    0xfd, 0x56, 0x1f, 0x5d, 0x3f, 0x6f, 0xf4, 0x4c, 0xd8, 0xfd, 0x0e, 0x27,
-+    0xc9, 0x5c, 0x2b, 0xbc, 0xc0, 0xa4, 0xe7, 0x23, 0x29, 0x02, 0x9f, 0x31,
-+    0xd6, 0xe9, 0xd7, 0x96, 0xf4, 0xe0, 0x5e, 0x0b, 0x0e, 0x13, 0xee, 0x3c,
-+    0x09, 0xed, 0xf2, 0x3d, 0x76, 0x91, 0xc3, 0xa4, 0x97, 0xae, 0xd4, 0x87,
-+    0xd0, 0x5d, 0xf6, 0x18, 0x47, 0x1f, 0x1d, 0x67, 0xf2, 0xcf, 0x63, 0xa0,
-+    0x91, 0x27, 0xf8, 0x93, 0x45, 0x75, 0x23, 0x3f, 0xd1, 0xf1, 0xad, 0x23,
-+    0xdd, 0x64, 0x93, 0x96, 0x41, 0x70, 0x7f, 0xf7, 0xf5, 0xa9, 0x89, 0xa2,
-+    0x34, 0xb0, 0x8d, 0x1b, 0xae, 0x19, 0x15, 0x49, 0x58, 0x23, 0x6d, 0x87,
-+    0x15, 0x4f, 0x81, 0x76, 0xfb, 0x23, 0xb5, 0xea, 0xcf, 0xac, 0x54, 0x8d,
-+    0x4e, 0x42, 0x2f, 0xeb, 0x0f, 0x63, 0xdb, 0x68, 0x37, 0xa8, 0xcf, 0x8b,
-+    0xab, 0xf5, 0xa4, 0x6e, 0x96, 0x2a, 0xb2, 0xd6, 0xbe, 0x9e, 0xbd, 0x0d,
-+    0xb4, 0x42, 0xa9, 0xcf, 0x01, 0x83, 0x8a, 0x17, 0x47, 0x76, 0xc4, 0xc6,
-+    0x83, 0x04, 0x95, 0x0b, 0xfc, 0x11, 0xc9, 0x62, 0xb8, 0x0c, 0x76, 0x84,
-+    0xd9, 0xb9, 0x37, 0xfa, 0xfc, 0x7c, 0xc2, 0x6d, 0x58, 0x3e, 0xb3, 0x04,
-+    0xbb, 0x8c, 0x8f, 0x48, 0xbc, 0x91, 0x27, 0xcc, 0xf9, 0xb7, 0x22, 0x19,
-+    0x83, 0x2e, 0x09, 0xb5, 0x72, 0xd9, 0x54, 0x1c, 0x4d, 0xa1, 0xea, 0x0b,
-+    0xf1, 0xc6, 0x08, 0x72, 0x46, 0x87, 0x7a, 0x6e, 0x80, 0x56, 0x0a, 0x8a,
-+    0xc0, 0xdd, 0x11, 0x6b, 0xd6, 0xdd, 0x47, 0xdf, 0x10, 0xd9, 0xd8, 0xea,
-+    0x7c, 0xb0, 0x8f, 0x03, 0x00, 0x2e, 0xc1, 0x8f, 0x44, 0xa8, 0xd3, 0x30,
-+    0x06, 0x89, 0xa2, 0xf9, 0x34, 0xad, 0xdc, 0x03, 0x85, 0xed, 0x51, 0xa7,
-+    0x82, 0x9c, 0xe7, 0x5d, 0x52, 0x93, 0x0c, 0x32, 0x9a, 0x5b, 0xe1, 0xaa,
-+    0xca, 0xb8, 0x02, 0x6d, 0x3a, 0xd4, 0xb1, 0x3a, 0xf0, 0x5f, 0xbe, 0xb5,
-+    0x0d, 0x10, 0x6b, 0x38, 0x32, 0xac, 0x76, 0x80, 0xbd, 0xca, 0x94, 0x71,
-+    0x7a, 0xf2, 0xc9, 0x35, 0x2a, 0xde, 0x9f, 0x42, 0x49, 0x18, 0x01, 0xab,
-+    0xbc, 0xef, 0x7c, 0x64, 0x3f, 0x58, 0x3d, 0x92, 0x59, 0xdb, 0x13, 0xdb,
-+    0x58, 0x6e, 0x0a, 0xe0, 0xb7, 0x91, 0x4a, 0x08, 0x20, 0xd6, 0x2e, 0x3c,
-+    0x45, 0xc9, 0x8b, 0x17, 0x79, 0xe7, 0xc7, 0x90, 0x99, 0x3a, 0x18, 0x25,
-+};
-+
-+#else
-+
-+// k25519Precomp[i][j] = (j+1)*256^i*B
-+static const ge_precomp k25519Precomp[32][8] = {
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1288382639258501, 245678601348599, 269427782077623,
-+                1462984067271730, 137412439391563
-+#else
-+                25967493, 19198397, 29566455, 3660896, 54414519, 4014786,
-+                27544626, 21800161, 61029707, 2047604
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                62697248952638, 204681361388450, 631292143396476,
-+                338455783676468, 1213667448819585
-+#else
-+                54563134, 934261, 64385954, 3049989, 66381436, 9406985,
-+                12720692, 5043384, 19500929, 18085054
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                301289933810280, 1259582250014073, 1422107436869536,
-+                796239922652654, 1953934009299142
-+#else
-+                58370664, 4489569, 9688441, 18769238, 10184608, 21191052,
-+                29287918, 11864899, 42594502, 29115885
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1380971894829527, 790832306631236, 2067202295274102,
-+                1995808275510000, 1566530869037010
-+#else
-+                54292951, 20578084, 45527620, 11784319, 41753206, 30803714,
-+                55390960, 29739860, 66750418, 23343128
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                463307831301544, 432984605774163, 1610641361907204,
-+                750899048855000, 1894842303421586
-+#else
-+                45405608, 6903824, 27185491, 6451973, 37531140, 24000426,
-+                51492312, 11189267, 40279186, 28235350
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                748439484463711, 1033211726465151, 1396005112841647,
-+                1611506220286469, 1972177495910992
-+#else
-+                26966623, 11152617, 32442495, 15396054, 14353839, 20802097,
-+                63980037, 24013313, 51636816, 29387734
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1601611775252272, 1720807796594148, 1132070835939856,
-+                1260455018889551, 2147779492816911
-+#else
-+                15636272, 23865875, 24204772, 25642034, 616976, 16869170,
-+                27787599, 18782243, 28944399, 32004408
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                316559037616741, 2177824224946892, 1459442586438991,
-+                1461528397712656, 751590696113597
-+#else
-+                16568933, 4717097, 55552716, 32452109, 15682895, 21747389,
-+                16354576, 21778470, 7689661, 11199574
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1850748884277385, 1200145853858453, 1068094770532492,
-+                672251375690438, 1586055907191707
-+#else
-+                30464137, 27578307, 55329429, 17883566, 23220364, 15915852,
-+                7512774, 10017326, 49359771, 23634074
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                934282339813791, 1846903124198670, 1172395437954843,
-+                1007037127761661, 1830588347719256
-+#else
-+                50071967, 13921891, 10945806, 27521001, 27105051, 17470053,
-+                38182653, 15006022, 3284568, 27277892
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1694390458783935, 1735906047636159, 705069562067493,
-+                648033061693059, 696214010414170
-+#else
-+                23599295, 25248385, 55915199, 25867015, 13236773, 10506355,
-+                7464579, 9656445, 13059162, 10374397
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1121406372216585, 192876649532226, 190294192191717,
-+                1994165897297032, 2245000007398739
-+#else
-+                7798537, 16710257, 3033922, 2874086, 28997861, 2835604,
-+                32406664, 29715387, 66467155, 33453106
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                769950342298419, 132954430919746, 844085933195555,
-+                974092374476333, 726076285546016
-+#else
-+                10861363, 11473154, 27284546, 1981175, 37044515, 12577860,
-+                32867885, 14515107, 51670560, 10819379
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                425251763115706, 608463272472562, 442562545713235,
-+                837766094556764, 374555092627893
-+#else
-+                4708026, 6336745, 20377586, 9066809, 55836755, 6594695,
-+                41455196, 12483687, 54440373, 5581305
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1086255230780037, 274979815921559, 1960002765731872,
-+                929474102396301, 1190409889297339
-+#else
-+                19563141, 16186464, 37722007, 4097518, 10237984, 29206317,
-+                28542349, 13850243, 43430843, 17738489
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1388594989461809, 316767091099457, 394298842192982,
-+                1230079486801005, 1440737038838979
-+#else
-+                51736881, 20691677, 32573249, 4720197, 40672342, 5875510,
-+                47920237, 18329612, 57289923, 21468654
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                7380825640100, 146210432690483, 304903576448906,
-+                1198869323871120, 997689833219095
-+#else
-+                58559652, 109982, 15149363, 2178705, 22900618, 4543417, 3044240,
-+                17864545, 1762327, 14866737
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1181317918772081, 114573476638901, 262805072233344,
-+                265712217171332, 294181933805782
-+#else
-+                48909169, 17603008, 56635573, 1707277, 49922944, 3916100,
-+                38872452, 3959420, 27914454, 4383652
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                665000864555967, 2065379846933859, 370231110385876,
-+                350988370788628, 1233371373142985
-+#else
-+                5153727, 9909285, 1723747, 30776558, 30523604, 5516873,
-+                19480852, 5230134, 43156425, 18378665
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2019367628972465, 676711900706637, 110710997811333,
-+                1108646842542025, 517791959672113
-+#else
-+                36839857, 30090922, 7665485, 10083793, 28475525, 1649722,
-+                20654025, 16520125, 30598449, 7715701
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                965130719900578, 247011430587952, 526356006571389,
-+                91986625355052, 2157223321444601
-+#else
-+                28881826, 14381568, 9657904, 3680757, 46927229, 7843315,
-+                35708204, 1370707, 29794553, 32145132
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2068619540119183, 1966274918058806, 957728544705549,
-+                729906502578991, 159834893065166
-+#else
-+                14499471, 30824833, 33917750, 29299779, 28494861, 14271267,
-+                30290735, 10876454, 33954766, 2381725
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2073601412052185, 31021124762708, 264500969797082,
-+                248034690651703, 1030252227928288
-+#else
-+                59913433, 30899068, 52378708, 462250, 39384538, 3941371,
-+                60872247, 3696004, 34808032, 15351954
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                551790716293402, 1989538725166328, 801169423371717,
-+                2052451893578887, 678432056995012
-+#else
-+                27431194, 8222322, 16448760, 29646437, 48401861, 11938354,
-+                34147463, 30583916, 29551812, 10109425
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1368953770187805, 790347636712921, 437508475667162,
-+                2142576377050580, 1932081720066286
-+#else
-+                53451805, 20399000, 35825113, 11777097, 21447386, 6519384,
-+                64730580, 31926875, 10092782, 28790261
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                953638594433374, 1092333936795051, 1419774766716690,
-+                805677984380077, 859228993502513
-+#else
-+                27939166, 14210322, 4677035, 16277044, 44144402, 21156292,
-+                34600109, 12005537, 49298737, 12803509
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1200766035879111, 20142053207432, 1465634435977050,
-+                1645256912097844, 295121984874596
-+#else
-+                17228999, 17892808, 65875336, 300139, 65883994, 21839654,
-+                30364212, 24516238, 18016356, 4397660
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1735718747031557, 1248237894295956, 1204753118328107,
-+                976066523550493, 65943769534592
-+#else
-+                56150021, 25864224, 4776340, 18600194, 27850027, 17952220,
-+                40489757, 14544524, 49631360, 982638
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1060098822528990, 1586825862073490, 212301317240126,
-+                1975302711403555, 666724059764335
-+#else
-+                29253598, 15796703, 64244882, 23645547, 10057022, 3163536,
-+                7332899, 29434304, 46061167, 9934962
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1091990273418756, 1572899409348578, 80968014455247,
-+                306009358661350, 1520450739132526
-+#else
-+                5793284, 16271923, 42977250, 23438027, 29188559, 1206517,
-+                52360934, 4559894, 36984942, 22656481
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1480517209436112, 1511153322193952, 1244343858991172,
-+                304788150493241, 369136856496443
-+#else
-+                39464912, 22061425, 16282656, 22517939, 28414020, 18542168,
-+                24191033, 4541697, 53770555, 5500567
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2151330273626164, 762045184746182, 1688074332551515,
-+                823046109005759, 907602769079491
-+#else
-+                12650548, 32057319, 9052870, 11355358, 49428827, 25154267,
-+                49678271, 12264342, 10874051, 13524335
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2047386910586836, 168470092900250, 1552838872594810,
-+                340951180073789, 360819374702533
-+#else
-+                25556948, 30508442, 714650, 2510400, 23394682, 23139102,
-+                33119037, 5080568, 44580805, 5376627
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1982622644432056, 2014393600336956, 128909208804214,
-+                1617792623929191, 105294281913815
-+#else
-+                41020600, 29543379, 50095164, 30016803, 60382070, 1920896,
-+                44787559, 24106988, 4535767, 1569007
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                980234343912898, 1712256739246056, 588935272190264,
-+                204298813091998, 841798321043288
-+#else
-+                64853442, 14606629, 45416424, 25514613, 28430648, 8775819,
-+                36614302, 3044289, 31848280, 12543772
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                197561292938973, 454817274782871, 1963754960082318,
-+                2113372252160468, 971377527342673
-+#else
-+                45080285, 2943892, 35251351, 6777305, 13784462, 29262229,
-+                39731668, 31491700, 7718481, 14474653
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                164699448829328, 3127451757672, 1199504971548753,
-+                1766155447043652, 1899238924683527
-+#else
-+                2385296, 2454213, 44477544, 46602, 62670929, 17874016, 656964,
-+                26317767, 24316167, 28300865
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                732262946680281, 1674412764227063, 2182456405662809,
-+                1350894754474250, 558458873295247
-+#else
-+                13741529, 10911568, 33875447, 24950694, 46931033, 32521134,
-+                33040650, 20129900, 46379407, 8321685
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2103305098582922, 1960809151316468, 715134605001343,
-+                1454892949167181, 40827143824949
-+#else
-+                21060490, 31341688, 15712756, 29218333, 1639039, 10656336,
-+                23845965, 21679594, 57124405, 608371
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1239289043050212, 1744654158124578, 758702410031698,
-+                1796762995074688, 1603056663766
-+#else
-+                53436132, 18466845, 56219170, 25997372, 61071954, 11305546,
-+                1123968, 26773855, 27229398, 23887
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2232056027107988, 987343914584615, 2115594492994461,
-+                1819598072792159, 1119305654014850
-+#else
-+                43864724, 33260226, 55364135, 14712570, 37643165, 31524814,
-+                12797023, 27114124, 65475458, 16678953
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                320153677847348, 939613871605645, 641883205761567,
-+                1930009789398224, 329165806634126
-+#else
-+                37608244, 4770661, 51054477, 14001337, 7830047, 9564805,
-+                65600720, 28759386, 49939598, 4904952
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                980930490474130, 1242488692177893, 1251446316964684,
-+                1086618677993530, 1961430968465772
-+#else
-+                24059538, 14617003, 19037157, 18514524, 19766092, 18648003,
-+                5169210, 16191880, 2128236, 29227599
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                276821765317453, 1536835591188030, 1305212741412361,
-+                61473904210175, 2051377036983058
-+#else
-+                50127693, 4124965, 58568254, 22900634, 30336521, 19449185,
-+                37302527, 916032, 60226322, 30567899
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                833449923882501, 1750270368490475, 1123347002068295,
-+                185477424765687, 278090826653186
-+#else
-+                44477957, 12419371, 59974635, 26081060, 50629959, 16739174,
-+                285431, 2763829, 15736322, 4143876
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                794524995833413, 1849907304548286, 53348672473145,
-+                1272368559505217, 1147304168324779
-+#else
-+                2379333, 11839345, 62998462, 27565766, 11274297, 794957, 212801,
-+                18959769, 23527083, 17096164
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1504846112759364, 1203096289004681, 562139421471418,
-+                274333017451844, 1284344053775441
-+#else
-+                33431108, 22423954, 49269897, 17927531, 8909498, 8376530,
-+                34483524, 4087880, 51919953, 19138217
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                483048732424432, 2116063063343382, 30120189902313,
-+                292451576741007, 1156379271702225
-+#else
-+                1767664, 7197987, 53903638, 31531796, 54017513, 448825, 5799055,
-+                4357868, 62334673, 17231393
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                928372153029038, 2147692869914564, 1455665844462196,
-+                1986737809425946, 185207050258089
-+#else
-+                6721966, 13833823, 43585476, 32003117, 26354292, 21691111,
-+                23365146, 29604700, 7390889, 2759800
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                137732961814206, 706670923917341, 1387038086865771,
-+                1965643813686352, 1384777115696347
-+#else
-+                4409022, 2052381, 23373853, 10530217, 7676779, 20668478,
-+                21302352, 29290375, 1244379, 20634787
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                481144981981577, 2053319313589856, 2065402289827512,
-+                617954271490316, 1106602634668125
-+#else
-+                62687625, 7169618, 4982368, 30596842, 30256824, 30776892,
-+                14086412, 9208236, 15886429, 16489664
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                696298019648792, 893299659040895, 1148636718636009,
-+                26734077349617, 2203955659340681
-+#else
-+                1996056, 10375649, 14346367, 13311202, 60234729, 17116020,
-+                53415665, 398368, 36502409, 32841498
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                657390353372855, 998499966885562, 991893336905797,
-+                810470207106761, 343139804608786
-+#else
-+                41801399, 9795879, 64331450, 14878808, 33577029, 14780362,
-+                13348553, 12076947, 36272402, 5113181
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                791736669492960, 934767652997115, 824656780392914,
-+                1759463253018643, 361530362383518
-+#else
-+                49338080, 11797795, 31950843, 13929123, 41220562, 12288343,
-+                36767763, 26218045, 13847710, 5387222
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2022541353055597, 2094700262587466, 1551008075025686,
-+                242785517418164, 695985404963562
-+#else
-+                48526701, 30138214, 17824842, 31213466, 22744342, 23111821,
-+                8763060, 3617786, 47508202, 10370990
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1287487199965223, 2215311941380308, 1552928390931986,
-+                1664859529680196, 1125004975265243
-+#else
-+                20246567, 19185054, 22358228, 33010720, 18507282, 23140436,
-+                14554436, 24808340, 32232923, 16763880
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                677434665154918, 989582503122485, 1817429540898386,
-+                1052904935475344, 1143826298169798
-+#else
-+                9648486, 10094563, 26416693, 14745928, 36734546, 27081810,
-+                11094160, 15689506, 3140038, 17044340
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                367266328308408, 318431188922404, 695629353755355,
-+                634085657580832, 24581612564426
-+#else
-+                50948792, 5472694, 31895588, 4744994, 8823515, 10365685,
-+                39884064, 9448612, 38334410, 366294
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                773360688841258, 1815381330538070, 363773437667376,
-+                539629987070205, 783280434248437
-+#else
-+                19153450, 11523972, 56012374, 27051289, 42461232, 5420646,
-+                28344573, 8041113, 719605, 11671788
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                180820816194166, 168937968377394, 748416242794470,
-+                1227281252254508, 1567587861004268
-+#else
-+                8678006, 2694440, 60300850, 2517371, 4964326, 11152271,
-+                51675948, 18287915, 27000812, 23358879
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                478775558583645, 2062896624554807, 699391259285399,
-+                358099408427873, 1277310261461761
-+#else
-+                51950941, 7134311, 8639287, 30739555, 59873175, 10421741,
-+                564065, 5336097, 6750977, 19033406
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1984740906540026, 1079164179400229, 1056021349262661,
-+                1659958556483663, 1088529069025527
-+#else
-+                11836410, 29574944, 26297893, 16080799, 23455045, 15735944,
-+                1695823, 24735310, 8169719, 16220347
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                580736401511151, 1842931091388998, 1177201471228238,
-+                2075460256527244, 1301133425678027
-+#else
-+                48993007, 8653646, 17578566, 27461813, 59083086, 17541668,
-+                55964556, 30926767, 61118155, 19388398
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1515728832059182, 1575261009617579, 1510246567196186,
-+                191078022609704, 116661716289141
-+#else
-+                43800366, 22586119, 15213227, 23473218, 36255258, 22504427,
-+                27884328, 2847284, 2655861, 1738395
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1295295738269652, 1714742313707026, 545583042462581,
-+                2034411676262552, 1513248090013606
-+#else
-+                39571412, 19301410, 41772562, 25551651, 57738101, 8129820,
-+                21651608, 30315096, 48021414, 22549153
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                230710545179830, 30821514358353, 760704303452229,
-+                390668103790604, 573437871383156
-+#else
-+                1533110, 3437855, 23735889, 459276, 29970501, 11335377,
-+                26030092, 5821408, 10478196, 8544890
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1169380107545646, 263167233745614, 2022901299054448,
-+                819900753251120, 2023898464874585
-+#else
-+                32173102, 17425121, 24896206, 3921497, 22579056, 30143578,
-+                19270448, 12217473, 17789017, 30158437
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2102254323485823, 1570832666216754, 34696906544624,
-+                1993213739807337, 70638552271463
-+#else
-+                36555903, 31326030, 51530034, 23407230, 13243888, 517024,
-+                15479401, 29701199, 30460519, 1052596
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                894132856735058, 548675863558441, 845349339503395,
-+                1942269668326667, 1615682209874691
-+#else
-+                55493970, 13323617, 32618793, 8175907, 51878691, 12596686,
-+                27491595, 28942073, 3179267, 24075541
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1287670217537834, 1222355136884920, 1846481788678694,
-+                1150426571265110, 1613523400722047
-+#else
-+                31947050, 19187781, 62468280, 18214510, 51982886, 27514722,
-+                52352086, 17142691, 19072639, 24043372
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                793388516527298, 1315457083650035, 1972286999342417,
-+                1901825953052455, 338269477222410
-+#else
-+                11685058, 11822410, 3158003, 19601838, 33402193, 29389366,
-+                5977895, 28339415, 473098, 5040608
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                550201530671806, 778605267108140, 2063911101902983,
-+                115500557286349, 2041641272971022
-+#else
-+                46817982, 8198641, 39698732, 11602122, 1290375, 30754672,
-+                28326861, 1721092, 47550222, 30422825
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                717255318455100, 519313764361315, 2080406977303708,
-+                541981206705521, 774328150311600
-+#else
-+                7881532, 10687937, 7578723, 7738378, 48157852, 31000479,
-+                21820785, 8076149, 39240368, 11538388
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                261715221532238, 1795354330069993, 1496878026850283,
-+                499739720521052, 389031152673770
-+#else
-+                47173198, 3899860, 18283497, 26752864, 51380203, 22305220,
-+                8754524, 7446702, 61432810, 5797015
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1997217696294013, 1717306351628065, 1684313917746180,
-+                1644426076011410, 1857378133465451
-+#else
-+                55813245, 29760862, 51326753, 25589858, 12708868, 25098233,
-+                2014098, 24503858, 64739691, 27677090
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1475434724792648, 76931896285979, 1116729029771667,
-+                2002544139318042, 725547833803938
-+#else
-+                44636488, 21985690, 39426843, 1146374, 18956691, 16640559,
-+                1192730, 29840233, 15123618, 10811505
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2022306639183567, 726296063571875, 315345054448644,
-+                1058733329149221, 1448201136060677
-+#else
-+                14352079, 30134717, 48166819, 10822654, 32750596, 4699007,
-+                67038501, 15776355, 38222085, 21579878
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1710065158525665, 1895094923036397, 123988286168546,
-+                1145519900776355, 1607510767693874
-+#else
-+                38867681, 25481956, 62129901, 28239114, 29416930, 1847569,
-+                46454691, 17069576, 4714546, 23953777
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                561605375422540, 1071733543815037, 131496498800990,
-+                1946868434569999, 828138133964203
-+#else
-+                15200332, 8368572, 19679101, 15970074, 35236190, 1959450,
-+                24611599, 29010600, 55362987, 12340219
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1548495173745801, 442310529226540, 998072547000384,
-+                553054358385281, 644824326376171
-+#else
-+                12876937, 23074376, 33134380, 6590940, 60801088, 14872439,
-+                9613953, 8241152, 15370987, 9608631
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1445526537029440, 2225519789662536, 914628859347385,
-+                1064754194555068, 1660295614401091
-+#else
-+                62965568, 21540023, 8446280, 33162829, 4407737, 13629032,
-+                59383996, 15866073, 38898243, 24740332
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1199690223111956, 24028135822341, 66638289244341,
-+                57626156285975, 565093967979607
-+#else
-+                26660628, 17876777, 8393733, 358047, 59707573, 992987, 43204631,
-+                858696, 20571223, 8420556
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                876926774220824, 554618976488214, 1012056309841565,
-+                839961821554611, 1414499340307677
-+#else
-+                14620696, 13067227, 51661590, 8264466, 14106269, 15080814,
-+                33531827, 12516406, 45534429, 21077682
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                703047626104145, 1266841406201770, 165556500219173,
-+                486991595001879, 1011325891650656
-+#else
-+                236881, 10476226, 57258, 18877408, 6472997, 2466984, 17258519,
-+                7256740, 8791136, 15069930
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1622861044480487, 1156394801573634, 1869132565415504,
-+                327103985777730, 2095342781472284
-+#else
-+                1276391, 24182514, 22949634, 17231625, 43615824, 27852245,
-+                14711874, 4874229, 36445724, 31223040
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                334886927423922, 489511099221528, 129160865966726,
-+                1720809113143481, 619700195649254
-+#else
-+                5855666, 4990204, 53397016, 7294283, 59304582, 1924646,
-+                65685689, 25642053, 34039526, 9234252
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1646545795166119, 1758370782583567, 714746174550637,
-+                1472693650165135, 898994790308209
-+#else
-+                20590503, 24535444, 31529743, 26201766, 64402029, 10650547,
-+                31559055, 21944845, 18979185, 13396066
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                333403773039279, 295772542452938, 1693106465353610,
-+                912330357530760, 471235657950362
-+#else
-+                24474287, 4968103, 22267082, 4407354, 24063882, 25229252,
-+                48291976, 13594781, 33514650, 7021958
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1811196219982022, 1068969825533602, 289602974833439,
-+                1988956043611592, 863562343398367
-+#else
-+                55541958, 26988926, 45743778, 15928891, 40950559, 4315420,
-+                41160136, 29637754, 45628383, 12868081
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                906282429780072, 2108672665779781, 432396390473936,
-+                150625823801893, 1708930497638539
-+#else
-+                38473832, 13504660, 19988037, 31421671, 21078224, 6443208,
-+                45662757, 2244499, 54653067, 25465048
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                925664675702328, 21416848568684, 1831436641861340,
-+                601157008940113, 371818055044496
-+#else
-+                36513336, 13793478, 61256044, 319135, 41385692, 27290532,
-+                33086545, 8957937, 51875216, 5540520
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1479786007267725, 1738881859066675, 68646196476567,
-+                2146507056100328, 1247662817535471
-+#else
-+                55478669, 22050529, 58989363, 25911358, 2620055, 1022908,
-+                43398120, 31985447, 50980335, 18591624
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                52035296774456, 939969390708103, 312023458773250,
-+                59873523517659, 1231345905848899
-+#else
-+                23152952, 775386, 27395463, 14006635, 57407746, 4649511,
-+                1689819, 892185, 55595587, 18348483
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                643355106415761, 290186807495774, 2013561737429023,
-+                319648069511546, 393736678496162
-+#else
-+                9770129, 9586738, 26496094, 4324120, 1556511, 30004408,
-+                27453818, 4763127, 47929250, 5867133
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                129358342392716, 1932811617704777, 1176749390799681,
-+                398040349861790, 1170779668090425
-+#else
-+                34343820, 1927589, 31726409, 28801137, 23962433, 17534932,
-+                27846558, 5931263, 37359161, 17445976
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2051980782668029, 121859921510665, 2048329875753063,
-+                1235229850149665, 519062146124755
-+#else
-+                27461885, 30576896, 22380809, 1815854, 44075111, 30522493,
-+                7283489, 18406359, 47582163, 7734628
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1608170971973096, 415809060360428, 1350468408164766,
-+                2038620059057678, 1026904485989112
-+#else
-+                59098600, 23963614, 55988460, 6196037, 29344158, 20123547,
-+                7585294, 30377806, 18549496, 15302069
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1837656083115103, 1510134048812070, 906263674192061,
-+                1821064197805734, 565375124676301
-+#else
-+                34450527, 27383209, 59436070, 22502750, 6258877, 13504381,
-+                10458790, 27135971, 58236621, 8424745
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                578027192365650, 2034800251375322, 2128954087207123,
-+                478816193810521, 2196171989962750
-+#else
-+                24687186, 8613276, 36441818, 30320886, 1863891, 31723888,
-+                19206233, 7134917, 55824382, 32725512
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1633188840273139, 852787172373708, 1548762607215796,
-+                1266275218902681, 1107218203325133
-+#else
-+                11334899, 24336410, 8025292, 12707519, 17523892, 23078361,
-+                10243737, 18868971, 62042829, 16498836
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                462189358480054, 1784816734159228, 1611334301651368,
-+                1303938263943540, 707589560319424
-+#else
-+                8911542, 6887158, 57524604, 26595841, 11145640, 24010752,
-+                17303924, 19430194, 6536640, 10543906
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1038829280972848, 38176604650029, 753193246598573,
-+                1136076426528122, 595709990562434
-+#else
-+                38162480, 15479762, 49642029, 568875, 65611181, 11223453,
-+                64439674, 16928857, 39873154, 8876770
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1408451820859834, 2194984964010833, 2198361797561729,
-+                1061962440055713, 1645147963442934
-+#else
-+                41365946, 20987567, 51458897, 32707824, 34082177, 32758143,
-+                33627041, 15824473, 66504438, 24514614
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                4701053362120, 1647641066302348, 1047553002242085,
-+                1923635013395977, 206970314902065
-+#else
-+                10330056, 70051, 7957388, 24551765, 9764901, 15609756, 27698697,
-+                28664395, 1657393, 3084098
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1750479161778571, 1362553355169293, 1891721260220598,
-+                966109370862782, 1024913988299801
-+#else
-+                10477963, 26084172, 12119565, 20303627, 29016246, 28188843,
-+                31280318, 14396151, 36875289, 15272408
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                212699049131723, 1117950018299775, 1873945661751056,
-+                1403802921984058, 130896082652698
-+#else
-+                54820555, 3169462, 28813183, 16658753, 25116432, 27923966,
-+                41934906, 20918293, 42094106, 1950503
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                636808533673210, 1262201711667560, 390951380330599,
-+                1663420692697294, 561951321757406
-+#else
-+                40928506, 9489186, 11053416, 18808271, 36055143, 5825629,
-+                58724558, 24786899, 15341278, 8373727
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                520731594438141, 1446301499955692, 273753264629267,
-+                1565101517999256, 1019411827004672
-+#else
-+                28685821, 7759505, 52730348, 21551571, 35137043, 4079241,
-+                298136, 23321830, 64230656, 15190419
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                926527492029409, 1191853477411379, 734233225181171,
-+                184038887541270, 1790426146325343
-+#else
-+                34175969, 13806335, 52771379, 17760000, 43104243, 10940927,
-+                8669718, 2742393, 41075551, 26679428
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1464651961852572, 1483737295721717, 1519450561335517,
-+                1161429831763785, 405914998179977
-+#else
-+                65528476, 21825014, 41129205, 22109408, 49696989, 22641577,
-+                9291593, 17306653, 54954121, 6048604
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                996126634382301, 796204125879525, 127517800546509,
-+                344155944689303, 615279846169038
-+#else
-+                36803549, 14843443, 1539301, 11864366, 20201677, 1900163,
-+                13934231, 5128323, 11213262, 9168384
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                738724080975276, 2188666632415296, 1961313708559162,
-+                1506545807547587, 1151301638969740
-+#else
-+                40828332, 11007846, 19408960, 32613674, 48515898, 29225851,
-+                62020803, 22449281, 20470156, 17155731
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                622917337413835, 1218989177089035, 1284857712846592,
-+                970502061709359, 351025208117090
-+#else
-+                43972811, 9282191, 14855179, 18164354, 59746048, 19145871,
-+                44324911, 14461607, 14042978, 5230683
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2067814584765580, 1677855129927492, 2086109782475197,
-+                235286517313238, 1416314046739645
-+#else
-+                29969548, 30812838, 50396996, 25001989, 9175485, 31085458,
-+                21556950, 3506042, 61174973, 21104723
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                586844262630358, 307444381952195, 458399356043426,
-+                602068024507062, 1028548203415243
-+#else
-+                63964118, 8744660, 19704003, 4581278, 46678178, 6830682,
-+                45824694, 8971512, 38569675, 15326562
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                678489922928203, 2016657584724032, 90977383049628,
-+                1026831907234582, 615271492942522
-+#else
-+                47644235, 10110287, 49846336, 30050539, 43608476, 1355668,
-+                51585814, 15300987, 46594746, 9168259
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                301225714012278, 1094837270268560, 1202288391010439,
-+                644352775178361, 1647055902137983
-+#else
-+                61755510, 4488612, 43305616, 16314346, 7780487, 17915493,
-+                38160505, 9601604, 33087103, 24543045
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1210746697896478, 1416608304244708, 686487477217856,
-+                1245131191434135, 1051238336855737
-+#else
-+                47665694, 18041531, 46311396, 21109108, 37284416, 10229460,
-+                39664535, 18553900, 61111993, 15664671
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1135604073198207, 1683322080485474, 769147804376683,
-+                2086688130589414, 900445683120379
-+#else
-+                23294591, 16921819, 44458082, 25083453, 27844203, 11461195,
-+                13099750, 31094076, 18151675, 13417686
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1971518477615628, 401909519527336, 448627091057375,
-+                1409486868273821, 1214789035034363
-+#else
-+                42385932, 29377914, 35958184, 5988918, 40250079, 6685064,
-+                1661597, 21002991, 15271675, 18101767
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1364039144731711, 1897497433586190, 2203097701135459,
-+                145461396811251, 1349844460790699
-+#else
-+                11433023, 20325767, 8239630, 28274915, 65123427, 32828713,
-+                48410099, 2167543, 60187563, 20114249
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1045230323257973, 818206601145807, 630513189076103,
-+                1672046528998132, 807204017562437
-+#else
-+                35672693, 15575145, 30436815, 12192228, 44645511, 9395378,
-+                57191156, 24915434, 12215109, 12028277
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                439961968385997, 386362664488986, 1382706320807688,
-+                309894000125359, 2207801346498567
-+#else
-+                14098381, 6555944, 23007258, 5757252, 51681032, 20603929,
-+                30123439, 4617780, 50208775, 32898803
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1229004686397588, 920643968530863, 123975893911178,
-+                681423993215777, 1400559197080973
-+#else
-+                63082644, 18313596, 11893167, 13718664, 52299402, 1847384,
-+                51288865, 10154008, 23973261, 20869958
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2003766096898049, 170074059235165, 1141124258967971,
-+                1485419893480973, 1573762821028725
-+#else
-+                40577025, 29858441, 65199965, 2534300, 35238307, 17004076,
-+                18341389, 22134481, 32013173, 23450893
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                729905708611432, 1270323270673202, 123353058984288,
-+                426460209632942, 2195574535456672
-+#else
-+                41629544, 10876442, 55337778, 18929291, 54739296, 1838103,
-+                21911214, 6354752, 4425632, 32716610
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1271140255321235, 2044363183174497, 52125387634689,
-+                1445120246694705, 942541986339084
-+#else
-+                56675475, 18941465, 22229857, 30463385, 53917697, 776728,
-+                49693489, 21533969, 4725004, 14044970
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1761608437466135, 583360847526804, 1586706389685493,
-+                2157056599579261, 1170692369685772
-+#else
-+                19268631, 26250011, 1555348, 8692754, 45634805, 23643767,
-+                6347389, 32142648, 47586572, 17444675
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                871476219910823, 1878769545097794, 2241832391238412,
-+                548957640601001, 690047440233174
-+#else
-+                42244775, 12986007, 56209986, 27995847, 55796492, 33405905,
-+                19541417, 8180106, 9282262, 10282508
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                297194732135507, 1366347803776820, 1301185512245601,
-+                561849853336294, 1533554921345731
-+#else
-+                40903763, 4428546, 58447668, 20360168, 4098401, 19389175,
-+                15522534, 8372215, 5542595, 22851749
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                999628998628371, 1132836708493400, 2084741674517453,
-+                469343353015612, 678782988708035
-+#else
-+                56546323, 14895632, 26814552, 16880582, 49628109, 31065071,
-+                64326972, 6993760, 49014979, 10114654
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2189427607417022, 699801937082607, 412764402319267,
-+                1478091893643349, 2244675696854460
-+#else
-+                47001790, 32625013, 31422703, 10427861, 59998115, 6150668,
-+                38017109, 22025285, 25953724, 33448274
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1712292055966563, 204413590624874, 1405738637332841,
-+                408981300829763, 861082219276721
-+#else
-+                62874467, 25515139, 57989738, 3045999, 2101609, 20947138,
-+                19390019, 6094296, 63793585, 12831124
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                508561155940631, 966928475686665, 2236717801150132,
-+                424543858577297, 2089272956986143
-+#else
-+                51110167, 7578151, 5310217, 14408357, 33560244, 33329692,
-+                31575953, 6326196, 7381791, 31132593
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                221245220129925, 1156020201681217, 491145634799213,
-+                542422431960839, 828100817819207
-+#else
-+                46206085, 3296810, 24736065, 17226043, 18374253, 7318640,
-+                6295303, 8082724, 51746375, 12339663
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                153756971240384, 1299874139923977, 393099165260502,
-+                1058234455773022, 996989038681183
-+#else
-+                27724736, 2291157, 6088201, 19369634, 1792726, 5857634,
-+                13848414, 15768922, 25091167, 14856294
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                559086812798481, 573177704212711, 1629737083816402,
-+                1399819713462595, 1646954378266038
-+#else
-+                48242193, 8331042, 24373479, 8541013, 66406866, 24284974,
-+                12927299, 20858939, 44926390, 24541532
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1887963056288059, 228507035730124, 1468368348640282,
-+                930557653420194, 613513962454686
-+#else
-+                55685435, 28132841, 11632844, 3405020, 30536730, 21880393,
-+                39848098, 13866389, 30146206, 9142070
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1224529808187553, 1577022856702685, 2206946542980843,
-+                625883007765001, 279930793512158
-+#else
-+                3924129, 18246916, 53291741, 23499471, 12291819, 32886066,
-+                39406089, 9326383, 58871006, 4171293
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1076287717051609, 1114455570543035, 187297059715481,
-+                250446884292121, 1885187512550540
-+#else
-+                51186905, 16037936, 6713787, 16606682, 45496729, 2790943,
-+                26396185, 3731949, 345228, 28091483
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                902497362940219, 76749815795675, 1657927525633846,
-+                1420238379745202, 1340321636548352
-+#else
-+                45781307, 13448258, 25284571, 1143661, 20614966, 24705045,
-+                2031538, 21163201, 50855680, 19972348
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1129576631190784, 1281994010027327, 996844254743018,
-+                257876363489249, 1150850742055018
-+#else
-+                31016192, 16832003, 26371391, 19103199, 62081514, 14854136,
-+                17477601, 3842657, 28012650, 17149012
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                628740660038789, 1943038498527841, 467786347793886,
-+                1093341428303375, 235413859513003
-+#else
-+                62033029, 9368965, 58546785, 28953529, 51858910, 6970559,
-+                57918991, 16292056, 58241707, 3507939
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                237425418909360, 469614029179605, 1512389769174935,
-+                1241726368345357, 441602891065214
-+#else
-+                29439664, 3537914, 23333589, 6997794, 49553303, 22536363,
-+                51899661, 18503164, 57943934, 6580395
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1736417953058555, 726531315520508, 1833335034432527,
-+                1629442561574747, 624418919286085
-+#else
-+                54923003, 25874643, 16438268, 10826160, 58412047, 27318820,
-+                17860443, 24280586, 65013061, 9304566
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1960754663920689, 497040957888962, 1909832851283095,
-+                1271432136996826, 2219780368020940
-+#else
-+                20714545, 29217521, 29088194, 7406487, 11426967, 28458727,
-+                14792666, 18945815, 5289420, 33077305
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1537037379417136, 1358865369268262, 2130838645654099,
-+                828733687040705, 1999987652890901
-+#else
-+                50443312, 22903641, 60948518, 20248671, 9192019, 31751970,
-+                17271489, 12349094, 26939669, 29802138
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                629042105241814, 1098854999137608, 887281544569320,
-+                1423102019874777, 7911258951561
-+#else
-+                54218966, 9373457, 31595848, 16374215, 21471720, 13221525,
-+                39825369, 21205872, 63410057, 117886
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1811562332665373, 1501882019007673, 2213763501088999,
-+                359573079719636, 36370565049116
-+#else
-+                22263325, 26994382, 3984569, 22379786, 51994855, 32987646,
-+                28311252, 5358056, 43789084, 541963
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                218907117361280, 1209298913016966, 1944312619096112,
-+                1130690631451061, 1342327389191701
-+#else
-+                16259200, 3261970, 2309254, 18019958, 50223152, 28972515,
-+                24134069, 16848603, 53771797, 20002236
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1369976867854704, 1396479602419169, 1765656654398856,
-+                2203659200586299, 998327836117241
-+#else
-+                9378160, 20414246, 44262881, 20809167, 28198280, 26310334,
-+                64709179, 32837080, 690425, 14876244
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2230701885562825, 1348173180338974, 2172856128624598,
-+                1426538746123771, 444193481326151
-+#else
-+                24977353, 33240048, 58884894, 20089345, 28432342, 32378079,
-+                54040059, 21257083, 44727879, 6618998
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                784210426627951, 918204562375674, 1284546780452985,
-+                1324534636134684, 1872449409642708
-+#else
-+                65570671, 11685645, 12944378, 13682314, 42719353, 19141238,
-+                8044828, 19737104, 32239828, 27901670
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                319638829540294, 596282656808406, 2037902696412608,
-+                1557219121643918, 341938082688094
-+#else
-+                48505798, 4762989, 66182614, 8885303, 38696384, 30367116,
-+                9781646, 23204373, 32779358, 5095274
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1901860206695915, 2004489122065736, 1625847061568236,
-+                973529743399879, 2075287685312905
-+#else
-+                34100715, 28339925, 34843976, 29869215, 9460460, 24227009,
-+                42507207, 14506723, 21639561, 30924196
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1371853944110545, 1042332820512553, 1949855697918254,
-+                1791195775521505, 37487364849293
-+#else
-+                50707921, 20442216, 25239337, 15531969, 3987758, 29055114,
-+                65819361, 26690896, 17874573, 558605
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                687200189577855, 1082536651125675, 644224940871546,
-+                340923196057951, 343581346747396
-+#else
-+                53508735, 10240080, 9171883, 16131053, 46239610, 9599699,
-+                33499487, 5080151, 2085892, 5119761
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2082717129583892, 27829425539422, 145655066671970,
-+                1690527209845512, 1865260509673478
-+#else
-+                44903700, 31034903, 50727262, 414690, 42089314, 2170429,
-+                30634760, 25190818, 35108870, 27794547
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1059729620568824, 2163709103470266, 1440302280256872,
-+                1769143160546397, 869830310425069
-+#else
-+                60263160, 15791201, 8550074, 32241778, 29928808, 21462176,
-+                27534429, 26362287, 44757485, 12961481
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1609516219779025, 777277757338817, 2101121130363987,
-+                550762194946473, 1905542338659364
-+#else
-+                42616785, 23983660, 10368193, 11582341, 43711571, 31309144,
-+                16533929, 8206996, 36914212, 28394793
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2024821921041576, 426948675450149, 595133284085473,
-+                471860860885970, 600321679413000
-+#else
-+                55987368, 30172197, 2307365, 6362031, 66973409, 8868176,
-+                50273234, 7031274, 7589640, 8945490
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                598474602406721, 1468128276358244, 1191923149557635,
-+                1501376424093216, 1281662691293476
-+#else
-+                34956097, 8917966, 6661220, 21876816, 65916803, 17761038,
-+                7251488, 22372252, 24099108, 19098262
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1721138489890707, 1264336102277790, 433064545421287,
-+                1359988423149466, 1561871293409447
-+#else
-+                5019539, 25646962, 4244126, 18840076, 40175591, 6453164,
-+                47990682, 20265406, 60876967, 23273695
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                719520245587143, 393380711632345, 132350400863381,
-+                1543271270810729, 1819543295798660
-+#else
-+                10853575, 10721687, 26480089, 5861829, 44113045, 1972174,
-+                65242217, 22996533, 63745412, 27113307
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                396397949784152, 1811354474471839, 1362679985304303,
-+                2117033964846756, 498041172552279
-+#else
-+                50106456, 5906789, 221599, 26991285, 7828207, 20305514,
-+                24362660, 31546264, 53242455, 7421391
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1812471844975748, 1856491995543149, 126579494584102,
-+                1036244859282620, 1975108050082550
-+#else
-+                8139908, 27007935, 32257645, 27663886, 30375718, 1886181,
-+                45933756, 15441251, 28826358, 29431403
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                650623932407995, 1137551288410575, 2125223403615539,
-+                1725658013221271, 2134892965117796
-+#else
-+                6267067, 9695052, 7709135, 16950835, 34239795, 31668296,
-+                14795159, 25714308, 13746020, 31812384
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                522584000310195, 1241762481390450, 1743702789495384,
-+                2227404127826575, 1686746002148897
-+#else
-+                28584883, 7787108, 60375922, 18503702, 22846040, 25983196,
-+                63926927, 33190907, 4771361, 25134474
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                427904865186312, 1703211129693455, 1585368107547509,
-+                1436984488744336, 761188534613978
-+#else
-+                24949256, 6376279, 39642383, 25379823, 48462709, 23623825,
-+                33543568, 21412737, 3569626, 11342593
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                318101947455002, 248138407995851, 1481904195303927,
-+                309278454311197, 1258516760217879
-+#else
-+                26514970, 4740088, 27912651, 3697550, 19331575, 22082093,
-+                6809885, 4608608, 7325975, 18753361
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1275068538599310, 513726919533379, 349926553492294,
-+                688428871968420, 1702400196000666
-+#else
-+                55490446, 19000001, 42787651, 7655127, 65739590, 5214311,
-+                39708324, 10258389, 49462170, 25367739
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1061864036265233, 961611260325381, 321859632700838,
-+                1045600629959517, 1985130202504038
-+#else
-+                11431185, 15823007, 26570245, 14329124, 18029990, 4796082,
-+                35662685, 15580663, 9280358, 29580745
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1558816436882417, 1962896332636523, 1337709822062152,
-+                1501413830776938, 294436165831932
-+#else
-+                66948081, 23228174, 44253547, 29249434, 46247496, 19933429,
-+                34297962, 22372809, 51563772, 4387440
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                818359826554971, 1862173000996177, 626821592884859,
-+                573655738872376, 1749691246745455
-+#else
-+                46309467, 12194511, 3937617, 27748540, 39954043, 9340369,
-+                42594872, 8548136, 20617071, 26072431
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1988022651432119, 1082111498586040, 1834020786104821,
-+                1454826876423687, 692929915223122
-+#else
-+                66170039, 29623845, 58394552, 16124717, 24603125, 27329039,
-+                53333511, 21678609, 24345682, 10325460
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2146513703733331, 584788900394667, 464965657279958,
-+                2183973639356127, 238371159456790
-+#else
-+                47253587, 31985546, 44906155, 8714033, 14007766, 6928528,
-+                16318175, 32543743, 4766742, 3552007
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1129007025494441, 2197883144413266, 265142755578169,
-+                971864464758890, 1983715884903702
-+#else
-+                45357481, 16823515, 1351762, 32751011, 63099193, 3950934,
-+                3217514, 14481909, 10988822, 29559670
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1291366624493075, 381456718189114, 1711482489312444,
-+                1815233647702022, 892279782992467
-+#else
-+                15564307, 19242862, 3101242, 5684148, 30446780, 25503076,
-+                12677126, 27049089, 58813011, 13296004
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                444548969917454, 1452286453853356, 2113731441506810,
-+                645188273895859, 810317625309512
-+#else
-+                57666574, 6624295, 36809900, 21640754, 62437882, 31497052,
-+                31521203, 9614054, 37108040, 12074673
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2242724082797924, 1373354730327868, 1006520110883049,
-+                2147330369940688, 1151816104883620
-+#else
-+                4771172, 33419193, 14290748, 20464580, 27992297, 14998318,
-+                65694928, 31997715, 29832612, 17163397
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1745720200383796, 1911723143175317, 2056329390702074,
-+                355227174309849, 879232794371100
-+#else
-+                7064884, 26013258, 47946901, 28486894, 48217594, 30641695,
-+                25825241, 5293297, 39986204, 13101589
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                163723479936298, 115424889803150, 1156016391581227,
-+                1894942220753364, 1970549419986329
-+#else
-+                64810282, 2439669, 59642254, 1719964, 39841323, 17225986,
-+                32512468, 28236839, 36752793, 29363474
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                681981452362484, 267208874112496, 1374683991933094,
-+                638600984916117, 646178654558546
-+#else
-+                37102324, 10162315, 33928688, 3981722, 50626726, 20484387,
-+                14413973, 9515896, 19568978, 9628812
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                13378654854251, 106237307029567, 1944412051589651,
-+                1841976767925457, 230702819835573
-+#else
-+                33053803, 199357, 15894591, 1583059, 27380243, 28973997,
-+                49269969, 27447592, 60817077, 3437739
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                260683893467075, 854060306077237, 913639551980112,
-+                4704576840123, 280254810808712
-+#else
-+                48129987, 3884492, 19469877, 12726490, 15913552, 13614290,
-+                44147131, 70103, 7463304, 4176122
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                715374893080287, 1173334812210491, 1806524662079626,
-+                1894596008000979, 398905715033393
-+#else
-+                39984863, 10659916, 11482427, 17484051, 12771466, 26919315,
-+                34389459, 28231680, 24216881, 5944158
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                500026409727661, 1596431288195371, 1420380351989370,
-+                985211561521489, 392444930785633
-+#else
-+                8894125, 7450974, 64444715, 23788679, 39028346, 21165316,
-+                19345745, 14680796, 11632993, 5847885
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2096421546958141, 1922523000950363, 789831022876840,
-+                427295144688779, 320923973161730
-+#else
-+                26942781, 31239115, 9129563, 28647825, 26024104, 11769399,
-+                55590027, 6367193, 57381634, 4782139
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1927770723575450, 1485792977512719, 1850996108474547,
-+                551696031508956, 2126047405475647
-+#else
-+                19916442, 28726022, 44198159, 22140040, 25606323, 27581991,
-+                33253852, 8220911, 6358847, 31680575
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2112099158080148, 742570803909715, 6484558077432,
-+                1951119898618916, 93090382703416
-+#else
-+                801428, 31472730, 16569427, 11065167, 29875704, 96627, 7908388,
-+                29073952, 53570360, 1387154
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                383905201636970, 859946997631870, 855623867637644,
-+                1017125780577795, 794250831877809
-+#else
-+                19646058, 5720633, 55692158, 12814208, 11607948, 12749789,
-+                14147075, 15156355, 45242033, 11835259
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                77571826285752, 999304298101753, 487841111777762,
-+                1038031143212339, 339066367948762
-+#else
-+                19299512, 1155910, 28703737, 14890794, 2925026, 7269399,
-+                26121523, 15467869, 40548314, 5052482
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                674994775520533, 266035846330789, 826951213393478,
-+                1405007746162285, 1781791018620876
-+#else
-+                64091413, 10058205, 1980837, 3964243, 22160966, 12322533,
-+                60677741, 20936246, 12228556, 26550755
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1001412661522686, 348196197067298, 1666614366723946,
-+                888424995032760, 580747687801357
-+#else
-+                32944382, 14922211, 44263970, 5188527, 21913450, 24834489,
-+                4001464, 13238564, 60994061, 8653814
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1939560076207777, 1409892634407635, 552574736069277,
-+                383854338280405, 190706709864139
-+#else
-+                22865569, 28901697, 27603667, 21009037, 14348957, 8234005,
-+                24808405, 5719875, 28483275, 2841751
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2177087163428741, 1439255351721944, 1208070840382793,
-+                2230616362004769, 1396886392021913
-+#else
-+                50687877, 32441126, 66781144, 21446575, 21886281, 18001658,
-+                65220897, 33238773, 19932057, 20815229
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                676962063230039, 1880275537148808, 2046721011602706,
-+                888463247083003, 1318301552024067
-+#else
-+                55452759, 10087520, 58243976, 28018288, 47830290, 30498519,
-+                3999227, 13239134, 62331395, 19644223
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1466980508178206, 617045217998949, 652303580573628,
-+                757303753529064, 207583137376902
-+#else
-+                1382174, 21859713, 17266789, 9194690, 53784508, 9720080,
-+                20403944, 11284705, 53095046, 3093229
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1511056752906902, 105403126891277, 493434892772846,
-+                1091943425335976, 1802717338077427
-+#else
-+                16650902, 22516500, 66044685, 1570628, 58779118, 7352752,
-+                66806440, 16271224, 43059443, 26862581
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1853982405405128, 1878664056251147, 1528011020803992,
-+                1019626468153565, 1128438412189035
-+#else
-+                45197768, 27626490, 62497547, 27994275, 35364760, 22769138,
-+                24123613, 15193618, 45456747, 16815042
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1963939888391106, 293456433791664, 697897559513649,
-+                985882796904380, 796244541237972
-+#else
-+                57172930, 29264984, 41829040, 4372841, 2087473, 10399484,
-+                31870908, 14690798, 17361620, 11864968
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                416770998629779, 389655552427054, 1314476859406756,
-+                1749382513022778, 1161905598739491
-+#else
-+                55801235, 6210371, 13206574, 5806320, 38091172, 19587231,
-+                54777658, 26067830, 41530403, 17313742
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1428358296490651, 1027115282420478, 304840698058337,
-+                441410174026628, 1819358356278573
-+#else
-+                14668443, 21284197, 26039038, 15305210, 25515617, 4542480,
-+                10453892, 6577524, 9145645, 27110552
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                204943430200135, 1554861433819175, 216426658514651,
-+                264149070665950, 2047097371738319
-+#else
-+                5974855, 3053895, 57675815, 23169240, 35243739, 3225008,
-+                59136222, 3936127, 61456591, 30504127
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1934415182909034, 1393285083565062, 516409331772960,
-+                1157690734993892, 121039666594268
-+#else
-+                30625386, 28825032, 41552902, 20761565, 46624288, 7695098,
-+                17097188, 17250936, 39109084, 1803631
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                662035583584445, 286736105093098, 1131773000510616,
-+                818494214211439, 472943792054479
-+#else
-+                63555773, 9865098, 61880298, 4272700, 61435032, 16864731,
-+                14911343, 12196514, 45703375, 7047411
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                665784778135882, 1893179629898606, 808313193813106,
-+                276797254706413, 1563426179676396
-+#else
-+                20093258, 9920966, 55970670, 28210574, 13161586, 12044805,
-+                34252013, 4124600, 34765036, 23296865
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                945205108984232, 526277562959295, 1324180513733566,
-+                1666970227868664, 153547609289173
-+#else
-+                46320040, 14084653, 53577151, 7842146, 19119038, 19731827,
-+                4752376, 24839792, 45429205, 2288037
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2031433403516252, 203996615228162, 170487168837083,
-+                981513604791390, 843573964916831
-+#else
-+                40289628, 30270716, 29965058, 3039786, 52635099, 2540456,
-+                29457502, 14625692, 42289247, 12570231
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1476570093962618, 838514669399805, 1857930577281364,
-+                2017007352225784, 317085545220047
-+#else
-+                66045306, 22002608, 16920317, 12494842, 1278292, 27685323,
-+                45948920, 30055751, 55134159, 4724942
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1461557121912842, 1600674043318359, 2157134900399597,
-+                1670641601940616, 127765583803283
-+#else
-+                17960970, 21778898, 62967895, 23851901, 58232301, 32143814,
-+                54201480, 24894499, 37532563, 1903855
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1293543509393474, 2143624609202546, 1058361566797508,
-+                214097127393994, 946888515472729
-+#else
-+                23134274, 19275300, 56426866, 31942495, 20684484, 15770816,
-+                54119114, 3190295, 26955097, 14109738
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                357067959932916, 1290876214345711, 521245575443703,
-+                1494975468601005, 800942377643885
-+#else
-+                15308788, 5320727, 36995055, 19235554, 22902007, 7767164,
-+                29425325, 22276870, 31960941, 11934971
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                566116659100033, 820247422481740, 994464017954148,
-+                327157611686365, 92591318111744
-+#else
-+                39713153, 8435795, 4109644, 12222639, 42480996, 14818668,
-+                20638173, 4875028, 10491392, 1379718
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                617256647603209, 1652107761099439, 1857213046645471,
-+                1085597175214970, 817432759830522
-+#else
-+                53949449, 9197840, 3875503, 24618324, 65725151, 27674630,
-+                33518458, 16176658, 21432314, 12180697
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                771808161440705, 1323510426395069, 680497615846440,
-+                851580615547985, 1320806384849017
-+#else
-+                55321537, 11500837, 13787581, 19721842, 44678184, 10140204,
-+                1465425, 12689540, 56807545, 19681548
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1219260086131915, 647169006596815, 79601124759706,
-+                2161724213426748, 404861897060198
-+#else
-+                5414091, 18168391, 46101199, 9643569, 12834970, 1186149,
-+                64485948, 32212200, 26128230, 6032912
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1327968293887866, 1335500852943256, 1401587164534264,
-+                558137311952440, 1551360549268902
-+#else
-+                40771450, 19788269, 32496024, 19900513, 17847800, 20885276,
-+                3604024, 8316894, 41233830, 23117073
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                417621685193956, 1429953819744454, 396157358457099,
-+                1940470778873255, 214000046234152
-+#else
-+                3296484, 6223048, 24680646, 21307972, 44056843, 5903204,
-+                58246567, 28915267, 12376616, 3188849
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1268047918491973, 2172375426948536, 1533916099229249,
-+                1761293575457130, 1590622667026765
-+#else
-+                29190469, 18895386, 27549112, 32370916, 3520065, 22857131,
-+                32049514, 26245319, 50999629, 23702124
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1627072914981959, 2211603081280073, 1912369601616504,
-+                1191770436221309, 2187309757525860
-+#else
-+                52364359, 24245275, 735817, 32955454, 46701176, 28496527,
-+                25246077, 17758763, 18640740, 32593455
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1149147819689533, 378692712667677, 828475842424202,
-+                2218619146419342, 70688125792186
-+#else
-+                60180029, 17123636, 10361373, 5642961, 4910474, 12345252,
-+                35470478, 33060001, 10530746, 1053335
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1299739417079761, 1438616663452759, 1536729078504412,
-+                2053896748919838, 1008421032591246
-+#else
-+                37842897, 19367626, 53570647, 21437058, 47651804, 22899047,
-+                35646494, 30605446, 24018830, 15026644
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2040723824657366, 399555637875075, 632543375452995,
-+                872649937008051, 1235394727030233
-+#else
-+                44516310, 30409154, 64819587, 5953842, 53668675, 9425630,
-+                25310643, 13003497, 64794073, 18408815
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2211311599327900, 2139787259888175, 938706616835350,
-+                12609661139114, 2081897930719789
-+#else
-+                39688860, 32951110, 59064879, 31885314, 41016598, 13987818,
-+                39811242, 187898, 43942445, 31022696
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1324994503390450, 336982330582631, 1183998925654177,
-+                1091654665913274, 48727673971319
-+#else
-+                45364466, 19743956, 1844839, 5021428, 56674465, 17642958,
-+                9716666, 16266922, 62038647, 726098
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1845522914617879, 1222198248335542, 150841072760134,
-+                1927029069940982, 1189913404498011
-+#else
-+                29370903, 27500434, 7334070, 18212173, 9385286, 2247707,
-+                53446902, 28714970, 30007387, 17731091
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1079559557592645, 2215338383666441, 1903569501302605,
-+                49033973033940, 305703433934152
-+#else
-+                66172485, 16086690, 23751945, 33011114, 65941325, 28365395,
-+                9137108, 730663, 9835848, 4555336
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                94653405416909, 1386121349852999, 1062130477891762,
-+                36553947479274, 833669648948846
-+#else
-+                43732429, 1410445, 44855111, 20654817, 30867634, 15826977,
-+                17693930, 544696, 55123566, 12422645
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1432015813136298, 440364795295369, 1395647062821501,
-+                1976874522764578, 934452372723352
-+#else
-+                31117226, 21338698, 53606025, 6561946, 57231997, 20796761,
-+                61990178, 29457725, 29120152, 13924425
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1296625309219774, 2068273464883862, 1858621048097805,
-+                1492281814208508, 2235868981918946
-+#else
-+                49707966, 19321222, 19675798, 30819676, 56101901, 27695611,
-+                57724924, 22236731, 7240930, 33317044
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1490330266465570, 1858795661361448, 1436241134969763,
-+                294573218899647, 1208140011028933
-+#else
-+                35747106, 22207651, 52101416, 27698213, 44655523, 21401660,
-+                1222335, 4389483, 3293637, 18002689
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1282462923712748, 741885683986255, 2027754642827561,
-+                518989529541027, 1826610009555945
-+#else
-+                50424044, 19110186, 11038543, 11054958, 53307689, 30215898,
-+                42789283, 7733546, 12796905, 27218610
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1525827120027511, 723686461809551, 1597702369236987,
-+                244802101764964, 1502833890372311
-+#else
-+                58349431, 22736595, 41689999, 10783768, 36493307, 23807620,
-+                38855524, 3647835, 3222231, 22393970
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                113622036244513, 1233740067745854, 674109952278496,
-+                2114345180342965, 166764512856263
-+#else
-+                18606113, 1693100, 41660478, 18384159, 4112352, 10045021,
-+                23603893, 31506198, 59558087, 2484984
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2041668749310338, 2184405322203901, 1633400637611036,
-+                2110682505536899, 2048144390084644
-+#else
-+                9255298, 30423235, 54952701, 32550175, 13098012, 24339566,
-+                16377219, 31451620, 47306788, 30519729
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                503058759232932, 760293024620937, 2027152777219493,
-+                666858468148475, 1539184379870952
-+#else
-+                44379556, 7496159, 61366665, 11329248, 19991973, 30206930,
-+                35390715, 9936965, 37011176, 22935634
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1916168475367211, 915626432541343, 883217071712575,
-+                363427871374304, 1976029821251593
-+#else
-+                21878571, 28553135, 4338335, 13643897, 64071999, 13160959,
-+                19708896, 5415497, 59748361, 29445138
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                678039535434506, 570587290189340, 1605302676614120,
-+                2147762562875701, 1706063797091704
-+#else
-+                27736842, 10103576, 12500508, 8502413, 63695848, 23920873,
-+                10436917, 32004156, 43449720, 25422331
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1439489648586438, 2194580753290951, 832380563557396,
-+                561521973970522, 584497280718389
-+#else
-+                19492550, 21450067, 37426887, 32701801, 63900692, 12403436,
-+                30066266, 8367329, 13243957, 8709688
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                187989455492609, 681223515948275, 1933493571072456,
-+                1872921007304880, 488162364135671
-+#else
-+                12015105, 2801261, 28198131, 10151021, 24818120, 28811299,
-+                55914672, 27908697, 5150967, 7274186
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1413466089534451, 410844090765630, 1397263346404072,
-+                408227143123410, 1594561803147811
-+#else
-+                2831347, 21062286, 1478974, 6122054, 23825128, 20820846,
-+                31097298, 6083058, 31021603, 23760822
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2102170800973153, 719462588665004, 1479649438510153,
-+                1097529543970028, 1302363283777685
-+#else
-+                64578913, 31324785, 445612, 10720828, 53259337, 22048494,
-+                43601132, 16354464, 15067285, 19406725
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                942065717847195, 1069313679352961, 2007341951411051,
-+                70973416446291, 1419433790163706
-+#else
-+                7840923, 14037873, 33744001, 15934015, 66380651, 29911725,
-+                21403987, 1057586, 47729402, 21151211
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1146565545556377, 1661971299445212, 406681704748893,
-+                564452436406089, 1109109865829139
-+#else
-+                915865, 17085158, 15608284, 24765302, 42751837, 6060029,
-+                49737545, 8410996, 59888403, 16527024
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2214421081775077, 1165671861210569, 1890453018796184,
-+                3556249878661, 442116172656317
-+#else
-+                32922597, 32997445, 20336073, 17369864, 10903704, 28169945,
-+                16957573, 52992, 23834301, 6588044
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                753830546620811, 1666955059895019, 1530775289309243,
-+                1119987029104146, 2164156153857580
-+#else
-+                32752011, 11232950, 3381995, 24839566, 22652987, 22810329,
-+                17159698, 16689107, 46794284, 32248439
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                615171919212796, 1523849404854568, 854560460547503,
-+                2067097370290715, 1765325848586042
-+#else
-+                62419196, 9166775, 41398568, 22707125, 11576751, 12733943,
-+                7924251, 30802151, 1976122, 26305405
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1094538949313667, 1796592198908825, 870221004284388,
-+                2025558921863561, 1699010892802384
-+#else
-+                21251203, 16309901, 64125849, 26771309, 30810596, 12967303,
-+                156041, 30183180, 12331344, 25317235
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1951351290725195, 1916457206844795, 198025184438026,
-+                1909076887557595, 1938542290318919
-+#else
-+                8651595, 29077400, 51023227, 28557437, 13002506, 2950805,
-+                29054427, 28447462, 10008135, 28886531
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1014323197538413, 869150639940606, 1756009942696599,
-+                1334952557375672, 1544945379082874
-+#else
-+                31486061, 15114593, 52847614, 12951353, 14369431, 26166587,
-+                16347320, 19892343, 8684154, 23021480
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                764055910920305, 1603590757375439, 146805246592357,
-+                1843313433854297, 954279890114939
-+#else
-+                19443825, 11385320, 24468943, 23895364, 43189605, 2187568,
-+                40845657, 27467510, 31316347, 14219878
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                80113526615750, 764536758732259, 1055139345100233,
-+                469252651759390, 617897512431515
-+#else
-+                38514374, 1193784, 32245219, 11392485, 31092169, 15722801,
-+                27146014, 6992409, 29126555, 9207390
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                74497112547268, 740094153192149, 1745254631717581,
-+                727713886503130, 1283034364416928
-+#else
-+                32382916, 1110093, 18477781, 11028262, 39697101, 26006320,
-+                62128346, 10843781, 59151264, 19118701
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                525892105991110, 1723776830270342, 1476444848991936,
-+                573789489857760, 133864092632978
-+#else
-+                2814918, 7836403, 27519878, 25686276, 46214848, 22000742,
-+                45614304, 8550129, 28346258, 1994730
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                542611720192581, 1986812262899321, 1162535242465837,
-+                481498966143464, 544600533583622
-+#else
-+                47530565, 8085544, 53108345, 29605809, 2785837, 17323125,
-+                47591912, 7174893, 22628102, 8115180
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                64123227344372, 1239927720647794, 1360722983445904,
-+                222610813654661, 62429487187991
-+#else
-+                36703732, 955510, 55975026, 18476362, 34661776, 20276352,
-+                41457285, 3317159, 57165847, 930271
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1793193323953132, 91096687857833, 70945970938921,
-+                2158587638946380, 1537042406482111
-+#else
-+                51805164, 26720662, 28856489, 1357446, 23421993, 1057177,
-+                24091212, 32165462, 44343487, 22903716
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1895854577604609, 1394895708949416, 1728548428495944,
-+                1140864900240149, 563645333603061
-+#else
-+                44357633, 28250434, 54201256, 20785565, 51297352, 25757378,
-+                52269845, 17000211, 65241845, 8398969
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                141358280486863, 91435889572504, 1087208572552643,
-+                1829599652522921, 1193307020643647
-+#else
-+                35139535, 2106402, 62372504, 1362500, 12813763, 16200670,
-+                22981545, 27263159, 18009407, 17781660
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1611230858525381, 950720175540785, 499589887488610,
-+                2001656988495019, 88977313255908
-+#else
-+                49887941, 24009210, 39324209, 14166834, 29815394, 7444469,
-+                29551787, 29827013, 19288548, 1325865
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1189080501479658, 2184348804772597, 1040818725742319,
-+                2018318290311834, 1712060030915354
-+#else
-+                15100138, 17718680, 43184885, 32549333, 40658671, 15509407,
-+                12376730, 30075286, 33166106, 25511682
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                873966876953756, 1090638350350440, 1708559325189137,
-+                672344594801910, 1320437969700239
-+#else
-+                20909212, 13023121, 57899112, 16251777, 61330449, 25459517,
-+                12412150, 10018715, 2213263, 19676059
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1508590048271766, 1131769479776094, 101550868699323,
-+                428297785557897, 561791648661744
-+#else
-+                32529814, 22479743, 30361438, 16864679, 57972923, 1513225,
-+                22922121, 6382134, 61341936, 8371347
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                756417570499462, 237882279232602, 2136263418594016,
-+                1701968045454886, 703713185137472
-+#else
-+                9923462, 11271500, 12616794, 3544722, 37110496, 31832805,
-+                12891686, 25361300, 40665920, 10486143
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1781187809325462, 1697624151492346, 1381393690939988,
-+                175194132284669, 1483054666415238
-+#else
-+                44511638, 26541766, 8587002, 25296571, 4084308, 20584370,
-+                361725, 2610596, 43187334, 22099236
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2175517777364616, 708781536456029, 955668231122942,
-+                1967557500069555, 2021208005604118
-+#else
-+                5408392, 32417741, 62139741, 10561667, 24145918, 14240566,
-+                31319731, 29318891, 19985174, 30118346
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1115135966606887, 224217372950782, 915967306279222,
-+                593866251291540, 561747094208006
-+#else
-+                53114407, 16616820, 14549246, 3341099, 32155958, 13648976,
-+                49531796, 8849296, 65030, 8370684
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1443163092879439, 391875531646162, 2180847134654632,
-+                464538543018753, 1594098196837178
-+#else
-+                58787919, 21504805, 31204562, 5839400, 46481576, 32497154,
-+                47665921, 6922163, 12743482, 23753914
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                850858855888869, 319436476624586, 327807784938441,
-+                740785849558761, 17128415486016
-+#else
-+                64747493, 12678784, 28815050, 4759974, 43215817, 4884716,
-+                23783145, 11038569, 18800704, 255233
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2132756334090067, 536247820155645, 48907151276867,
-+                608473197600695, 1261689545022784
-+#else
-+                61839187, 31780545, 13957885, 7990715, 23132995, 728773,
-+                13393847, 9066957, 19258688, 18800639
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1525176236978354, 974205476721062, 293436255662638,
-+                148269621098039, 137961998433963
-+#else
-+                64172210, 22726896, 56676774, 14516792, 63468078, 4372540,
-+                35173943, 2209389, 65584811, 2055793
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1121075518299410, 2071745529082111, 1265567917414828,
-+                1648196578317805, 496232102750820
-+#else
-+                580882, 16705327, 5468415, 30871414, 36182444, 18858431,
-+                59905517, 24560042, 37087844, 7394434
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                122321229299801, 1022922077493685, 2001275453369484,
-+                2017441881607947, 993205880778002
-+#else
-+                23838809, 1822728, 51370421, 15242726, 8318092, 29821328,
-+                45436683, 30062226, 62287122, 14799920
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                654925550560074, 1168810995576858, 575655959430926,
-+                905758704861388, 496774564663534
-+#else
-+                13345610, 9759151, 3371034, 17416641, 16353038, 8577942,
-+                31129804, 13496856, 58052846, 7402517
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1954109525779738, 2117022646152485, 338102630417180,
-+                1194140505732026, 107881734943492
-+#else
-+                2286874, 29118501, 47066405, 31546095, 53412636, 5038121,
-+                11006906, 17794080, 8205060, 1607563
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1714785840001267, 2036500018681589, 1876380234251966,
-+                2056717182974196, 1645855254384642
-+#else
-+                14414067, 25552300, 3331829, 30346215, 22249150, 27960244,
-+                18364660, 30647474, 30019586, 24525154
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                106431476499341, 62482972120563, 1513446655109411,
-+                807258751769522, 538491469114
-+#else
-+                39420813, 1585952, 56333811, 931068, 37988643, 22552112,
-+                52698034, 12029092, 9944378, 8024
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2002850762893643, 1243624520538135, 1486040410574605,
-+                2184752338181213, 378495998083531
-+#else
-+                4368715, 29844802, 29874199, 18531449, 46878477, 22143727,
-+                50994269, 32555346, 58966475, 5640029
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                922510868424903, 1089502620807680, 402544072617374,
-+                1131446598479839, 1290278588136533
-+#else
-+                10299591, 13746483, 11661824, 16234854, 7630238, 5998374,
-+                9809887, 16859868, 15219797, 19226649
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1867998812076769, 715425053580701, 39968586461416,
-+                2173068014586163, 653822651801304
-+#else
-+                27425505, 27835351, 3055005, 10660664, 23458024, 595578,
-+                51710259, 32381236, 48766680, 9742716
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                162892278589453, 182585796682149, 75093073137630,
-+                497037941226502, 133871727117371
-+#else
-+                6744077, 2427284, 26042789, 2720740, 66260958, 1118973,
-+                32324614, 7406442, 12420155, 1994844
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1914596576579670, 1608999621851578, 1987629837704609,
-+                1519655314857977, 1819193753409464
-+#else
-+                14012502, 28529712, 48724410, 23975962, 40623521, 29617992,
-+                54075385, 22644628, 24319928, 27108099
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1949315551096831, 1069003344994464, 1939165033499916,
-+                1548227205730856, 1933767655861407
-+#else
-+                16412671, 29047065, 10772640, 15929391, 50040076, 28895810,
-+                10555944, 23070383, 37006495, 28815383
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1730519386931635, 1393284965610134, 1597143735726030,
-+                416032382447158, 1429665248828629
-+#else
-+                22397363, 25786748, 57815702, 20761563, 17166286, 23799296,
-+                39775798, 6199365, 21880021, 21303672
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                360275475604565, 547835731063078, 215360904187529,
-+                596646739879007, 332709650425085
-+#else
-+                62825557, 5368522, 35991846, 8163388, 36785801, 3209127,
-+                16557151, 8890729, 8840445, 4957760
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                47602113726801, 1522314509708010, 437706261372925,
-+                814035330438027, 335930650933545
-+#else
-+                51661137, 709326, 60189418, 22684253, 37330941, 6522331,
-+                45388683, 12130071, 52312361, 5005756
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1291597595523886, 1058020588994081, 402837842324045,
-+                1363323695882781, 2105763393033193
-+#else
-+                64994094, 19246303, 23019041, 15765735, 41839181, 6002751,
-+                10183197, 20315106, 50713577, 31378319
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                109521982566564, 1715257748585139, 1112231216891516,
-+                2046641005101484, 134249157157013
-+#else
-+                48083108, 1632004, 13466291, 25559332, 43468412, 16573536,
-+                35094956, 30497327, 22208661, 2000468
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2156991030936798, 2227544497153325, 1869050094431622,
-+                754875860479115, 1754242344267058
-+#else
-+                3065054, 32141671, 41510189, 33192999, 49425798, 27851016,
-+                58944651, 11248526, 63417650, 26140247
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1846089562873800, 98894784984326, 1412430299204844,
-+                171351226625762, 1100604760929008
-+#else
-+                10379208, 27508878, 8877318, 1473647, 37817580, 21046851,
-+                16690914, 2553332, 63976176, 16400288
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                84172382130492, 499710970700046, 425749630620778,
-+                1762872794206857, 612842602127960
-+#else
-+                15716668, 1254266, 48636174, 7446273, 58659946, 6344163,
-+                45011593, 26268851, 26894936, 9132066
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                868309334532756, 1703010512741873, 1952690008738057,
-+                4325269926064, 2071083554962116
-+#else
-+                24158868, 12938817, 11085297, 25376834, 39045385, 29097348,
-+                36532400, 64451, 60291780, 30861549
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                523094549451158, 401938899487815, 1407690589076010,
-+                2022387426254453, 158660516411257
-+#else
-+                13488534, 7794716, 22236231, 5989356, 25426474, 20976224,
-+                2350709, 30135921, 62420857, 2364225
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                612867287630009, 448212612103814, 571629077419196,
-+                1466796750919376, 1728478129663858
-+#else
-+                16335033, 9132434, 25640582, 6678888, 1725628, 8517937,
-+                55301840, 21856974, 15445874, 25756331
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1723848973783452, 2208822520534681, 1718748322776940,
-+                1974268454121942, 1194212502258141
-+#else
-+                29004188, 25687351, 28661401, 32914020, 54314860, 25611345,
-+                31863254, 29418892, 66830813, 17795152
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1254114807944608, 977770684047110, 2010756238954993,
-+                1783628927194099, 1525962994408256
-+#else
-+                60986784, 18687766, 38493958, 14569918, 56250865, 29962602,
-+                10343411, 26578142, 37280576, 22738620
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                232464058235826, 1948628555342434, 1835348780427694,
-+                1031609499437291, 64472106918373
-+#else
-+                27081650, 3463984, 14099042, 29036828, 1616302, 27348828,
-+                29542635, 15372179, 17293797, 960709
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                767338676040683, 754089548318405, 1523192045639075,
-+                435746025122062, 512692508440385
-+#else
-+                20263915, 11434237, 61343429, 11236809, 13505955, 22697330,
-+                50997518, 6493121, 47724353, 7639713
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1255955808701983, 1700487367990941, 1166401238800299,
-+                1175121994891534, 1190934801395380
-+#else
-+                64278047, 18715199, 25403037, 25339236, 58791851, 17380732,
-+                18006286, 17510682, 29994676, 17746311
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                349144008168292, 1337012557669162, 1475912332999108,
-+                1321618454900458, 47611291904320
-+#else
-+                9769828, 5202651, 42951466, 19923039, 39057860, 21992807,
-+                42495722, 19693649, 35924288, 709463
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                877519947135419, 2172838026132651, 272304391224129,
-+                1655143327559984, 886229406429814
-+#else
-+                12286395, 13076066, 45333675, 32377809, 42105665, 4057651,
-+                35090736, 24663557, 16102006, 13205847
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                375806028254706, 214463229793940, 572906353144089,
-+                572168269875638, 697556386112979
-+#else
-+                13733362, 5599946, 10557076, 3195751, 61550873, 8536969,
-+                41568694, 8525971, 10151379, 10394400
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1168827102357844, 823864273033637, 2071538752104697,
-+                788062026895924, 599578340743362
-+#else
-+                4024660, 17416881, 22436261, 12276534, 58009849, 30868332,
-+                19698228, 11743039, 33806530, 8934413
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1948116082078088, 2054898304487796, 2204939184983900,
-+                210526805152138, 786593586607626
-+#else
-+                51229064, 29029191, 58528116, 30620370, 14634844, 32856154,
-+                57659786, 3137093, 55571978, 11721157
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1915320147894736, 156481169009469, 655050471180417,
-+                592917090415421, 2165897438660879
-+#else
-+                17555920, 28540494, 8268605, 2331751, 44370049, 9761012,
-+                9319229, 8835153, 57903375, 32274386
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1726336468579724, 1119932070398949, 1929199510967666,
-+                33918788322959, 1836837863503150
-+#else
-+                66647436, 25724417, 20614117, 16688288, 59594098, 28747312,
-+                22300303, 505429, 6108462, 27371017
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                829996854845988, 217061778005138, 1686565909803640,
-+                1346948817219846, 1723823550730181
-+#else
-+                62038564, 12367916, 36445330, 3234472, 32617080, 25131790,
-+                29880582, 20071101, 40210373, 25686972
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                384301494966394, 687038900403062, 2211195391021739,
-+                254684538421383, 1245698430589680
-+#else
-+                35133562, 5726538, 26934134, 10237677, 63935147, 32949378,
-+                24199303, 3795095, 7592688, 18562353
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1247567493562688, 1978182094455847, 183871474792955,
-+                806570235643435, 288461518067916
-+#else
-+                21594432, 18590204, 17466407, 29477210, 32537083, 2739898,
-+                6407723, 12018833, 38852812, 4298411
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1449077384734201, 38285445457996, 2136537659177832,
-+                2146493000841573, 725161151123125
-+#else
-+                46458361, 21592935, 39872588, 570497, 3767144, 31836892,
-+                13891941, 31985238, 13717173, 10805743
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1201928866368855, 800415690605445, 1703146756828343,
-+                997278587541744, 1858284414104014
-+#else
-+                52432215, 17910135, 15287173, 11927123, 24177847, 25378864,
-+                66312432, 14860608, 40169934, 27690595
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                356468809648877, 782373916933152, 1718002439402870,
-+                1392222252219254, 663171266061951
-+#else
-+                12962541, 5311799, 57048096, 11658279, 18855286, 25600231,
-+                13286262, 20745728, 62727807, 9882021
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                759628738230460, 1012693474275852, 353780233086498,
-+                246080061387552, 2030378857679162
-+#else
-+                18512060, 11319350, 46985740, 15090308, 18818594, 5271736,
-+                44380960, 3666878, 43141434, 30255002
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2040672435071076, 888593182036908, 1298443657189359,
-+                1804780278521327, 354070726137060
-+#else
-+                60319844, 30408388, 16192428, 13241070, 15898607, 19348318,
-+                57023983, 26893321, 64705764, 5276064
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1894938527423184, 1463213041477277, 474410505497651,
-+                247294963033299, 877975941029128
-+#else
-+                30169808, 28236784, 26306205, 21803573, 27814963, 7069267,
-+                7152851, 3684982, 1449224, 13082861
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                207937160991127, 12966911039119, 820997788283092,
-+                1010440472205286, 1701372890140810
-+#else
-+                10342807, 3098505, 2119311, 193222, 25702612, 12233820,
-+                23697382, 15056736, 46092426, 25352431
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                218882774543183, 533427444716285, 1233243976733245,
-+                435054256891319, 1509568989549904
-+#else
-+                33958735, 3261607, 22745853, 7948688, 19370557, 18376767,
-+                40936887, 6482813, 56808784, 22494330
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1888838535711826, 1052177758340622, 1213553803324135,
-+                169182009127332, 463374268115872
-+#else
-+                32869458, 28145887, 25609742, 15678670, 56421095, 18083360,
-+                26112420, 2521008, 44444576, 6904814
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                299137589460312, 1594371588983567, 868058494039073,
-+                257771590636681, 1805012993142921
-+#else
-+                29506904, 4457497, 3377935, 23757988, 36598817, 12935079,
-+                1561737, 3841096, 38105225, 26896789
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1806842755664364, 2098896946025095, 1356630998422878,
-+                1458279806348064, 347755825962072
-+#else
-+                10340844, 26924055, 48452231, 31276001, 12621150, 20215377,
-+                30878496, 21730062, 41524312, 5181965
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1402334161391744, 1560083671046299, 1008585416617747,
-+                1147797150908892, 1420416683642459
-+#else
-+                25940096, 20896407, 17324187, 23247058, 58437395, 15029093,
-+                24396252, 17103510, 64786011, 21165857
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                665506704253369, 273770475169863, 799236974202630,
-+                848328990077558, 1811448782807931
-+#else
-+                45343161, 9916822, 65808455, 4079497, 66080518, 11909558,
-+                1782390, 12641087, 20603771, 26992690
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1468412523962641, 771866649897997, 1931766110147832,
-+                799561180078482, 524837559150077
-+#else
-+                48226577, 21881051, 24849421, 11501709, 13161720, 28785558,
-+                1925522, 11914390, 4662781, 7820689
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2223212657821850, 630416247363666, 2144451165500328,
-+                816911130947791, 1024351058410032
-+#else
-+                12241050, 33128450, 8132690, 9393934, 32846760, 31954812,
-+                29749455, 12172924, 16136752, 15264020
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1266603897524861, 156378408858100, 1275649024228779,
-+                447738405888420, 253186462063095
-+#else
-+                56758909, 18873868, 58896884, 2330219, 49446315, 19008651,
-+                10658212, 6671822, 19012087, 3772772
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2022215964509735, 136144366993649, 1800716593296582,
-+                1193970603800203, 871675847064218
-+#else
-+                3753511, 30133366, 10617073, 2028709, 14841030, 26832768,
-+                28718731, 17791548, 20527770, 12988982
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1862751661970328, 851596246739884, 1519315554814041,
-+                1542798466547449, 1417975335901520
-+#else
-+                52286360, 27757162, 63400876, 12689772, 66209881, 22639565,
-+                42925817, 22989488, 3299664, 21129479
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1228168094547481, 334133883362894, 587567568420081,
-+                433612590281181, 603390400373205
-+#else
-+                50331161, 18301130, 57466446, 4978982, 3308785, 8755439,
-+                6943197, 6461331, 41525717, 8991217
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                121893973206505, 1843345804916664, 1703118377384911,
-+                497810164760654, 101150811654673
-+#else
-+                49882601, 1816361, 65435576, 27467992, 31783887, 25378441,
-+                34160718, 7417949, 36866577, 1507264
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                458346255946468, 290909935619344, 1452768413850679,
-+                550922875254215, 1537286854336538
-+#else
-+                29692644, 6829891, 56610064, 4334895, 20945975, 21647936,
-+                38221255, 8209390, 14606362, 22907359
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                584322311184395, 380661238802118, 114839394528060,
-+                655082270500073, 2111856026034852
-+#else
-+                63627275, 8707080, 32188102, 5672294, 22096700, 1711240,
-+                34088169, 9761486, 4170404, 31469107
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                996965581008991, 2148998626477022, 1012273164934654,
-+                1073876063914522, 1688031788934939
-+#else
-+                55521375, 14855944, 62981086, 32022574, 40459774, 15084045,
-+                22186522, 16002000, 52832027, 25153633
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                923487018849600, 2085106799623355, 528082801620136,
-+                1606206360876188, 735907091712524
-+#else
-+                62297408, 13761028, 35404987, 31070512, 63796392, 7869046,
-+                59995292, 23934339, 13240844, 10965870
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1697697887804317, 1335343703828273, 831288615207040,
-+                949416685250051, 288760277392022
-+#else
-+                59366301, 25297669, 52340529, 19898171, 43876480, 12387165,
-+                4498947, 14147411, 29514390, 4302863
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1419122478109648, 1325574567803701, 602393874111094,
-+                2107893372601700, 1314159682671307
-+#else
-+                53695440, 21146572, 20757301, 19752600, 14785142, 8976368,
-+                62047588, 31410058, 17846987, 19582505
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2201150872731804, 2180241023425241, 97663456423163,
-+                1633405770247824, 848945042443986
-+#else
-+                64864412, 32799703, 62511833, 32488122, 60861691, 1455298,
-+                45461136, 24339642, 61886162, 12650266
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1173339555550611, 818605084277583, 47521504364289,
-+                924108720564965, 735423405754506
-+#else
-+                57202067, 17484121, 21134159, 12198166, 40044289, 708125,
-+                387813, 13770293, 47974538, 10958662
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                830104860549448, 1886653193241086, 1600929509383773,
-+                1475051275443631, 286679780900937
-+#else
-+                22470984, 12369526, 23446014, 28113323, 45588061, 23855708,
-+                55336367, 21979976, 42025033, 4271861
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1577111294832995, 1030899169768747, 144900916293530,
-+                1964672592979567, 568390100955250
-+#else
-+                41939299, 23500789, 47199531, 15361594, 61124506, 2159191,
-+                75375, 29275903, 34582642, 8469672
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                278388655910247, 487143369099838, 927762205508727,
-+                181017540174210, 1616886700741287
-+#else
-+                15854951, 4148314, 58214974, 7259001, 11666551, 13824734,
-+                36577666, 2697371, 24154791, 24093489
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1191033906638969, 940823957346562, 1606870843663445,
-+                861684761499847, 658674867251089
-+#else
-+                15446137, 17747788, 29759746, 14019369, 30811221, 23944241,
-+                35526855, 12840103, 24913809, 9815020
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1875032594195546, 1427106132796197, 724736390962158,
-+                901860512044740, 635268497268760
-+#else
-+                62399578, 27940162, 35267365, 21265538, 52665326, 10799413,
-+                58005188, 13438768, 18735128, 9466238
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                622869792298357, 1903919278950367, 1922588621661629,
-+                1520574711600434, 1087100760174640
-+#else
-+                11933045, 9281483, 5081055, 28370608, 64480701, 28648802,
-+                59381042, 22658328, 44380208, 16199063
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                25465949416618, 1693639527318811, 1526153382657203,
-+                125943137857169, 145276964043999
-+#else
-+                14576810, 379472, 40322331, 25237195, 37682355, 22741457,
-+                67006097, 1876698, 30801119, 2164795
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                214739857969358, 920212862967915, 1939901550972269,
-+                1211862791775221, 85097515720120
-+#else
-+                15995086, 3199873, 13672555, 13712240, 47730029, 28906785,
-+                54027253, 18058162, 53616056, 1268051
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2006245852772938, 734762734836159, 254642929763427,
-+                1406213292755966, 239303749517686
-+#else
-+                56818250, 29895392, 63822271, 10948817, 23037027, 3794475,
-+                63638526, 20954210, 50053494, 3565903
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1619678837192149, 1919424032779215, 1357391272956794,
-+                1525634040073113, 1310226789796241
-+#else
-+                29210069, 24135095, 61189071, 28601646, 10834810, 20226706,
-+                50596761, 22733718, 39946641, 19523900
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1040763709762123, 1704449869235352, 605263070456329,
-+                1998838089036355, 1312142911487502
-+#else
-+                53946955, 15508587, 16663704, 25398282, 38758921, 9019122,
-+                37925443, 29785008, 2244110, 19552453
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1996723311435669, 1844342766567060, 985455700466044,
-+                1165924681400960, 311508689870129
-+#else
-+                61955989, 29753495, 57802388, 27482848, 16243068, 14684434,
-+                41435776, 17373631, 13491505, 4641841
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                43173156290518, 2202883069785309, 1137787467085917,
-+                1733636061944606, 1394992037553852
-+#else
-+                10813398, 643330, 47920349, 32825515, 30292061, 16954354,
-+                27548446, 25833190, 14476988, 20787001
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                670078326344559, 555655025059356, 471959386282438,
-+                2141455487356409, 849015953823125
-+#else
-+                10292079, 9984945, 6481436, 8279905, 59857350, 7032742,
-+                27282937, 31910173, 39196053, 12651323
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2197214573372804, 794254097241315, 1030190060513737,
-+                267632515541902, 2040478049202624
-+#else
-+                35923332, 32741048, 22271203, 11835308, 10201545, 15351028,
-+                17099662, 3988035, 21721536, 30405492
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1812516004670529, 1609256702920783, 1706897079364493,
-+                258549904773295, 996051247540686
-+#else
-+                10202177, 27008593, 35735631, 23979793, 34958221, 25434748,
-+                54202543, 3852693, 13216206, 14842320
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1540374301420584, 1764656898914615, 1810104162020396,
-+                923808779163088, 664390074196579
-+#else
-+                51293224, 22953365, 60569911, 26295436, 60124204, 26972653,
-+                35608016, 13765823, 39674467, 9900183
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1323460699404750, 1262690757880991, 871777133477900,
-+                1060078894988977, 1712236889662886
-+#else
-+                14465486, 19721101, 34974879, 18815558, 39665676, 12990491,
-+                33046193, 15796406, 60056998, 25514317
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1696163952057966, 1391710137550823, 608793846867416,
-+                1034391509472039, 1780770894075012
-+#else
-+                30924398, 25274812, 6359015, 20738097, 16508376, 9071735,
-+                41620263, 15413634, 9524356, 26535554
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1367603834210841, 2131988646583224, 890353773628144,
-+                1908908219165595, 270836895252891
-+#else
-+                12274201, 20378885, 32627640, 31769106, 6736624, 13267305,
-+                5237659, 28444949, 15663515, 4035784
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                597536315471731, 40375058742586, 1942256403956049,
-+                1185484645495932, 312666282024145
-+#else
-+                64157555, 8903984, 17349946, 601635, 50676049, 28941875,
-+                53376124, 17665097, 44850385, 4659090
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1919411405316294, 1234508526402192, 1066863051997083,
-+                1008444703737597, 1348810787701552
-+#else
-+                50192582, 28601458, 36715152, 18395610, 20774811, 15897498,
-+                5736189, 15026997, 64930608, 20098846
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2102881477513865, 1570274565945361, 1573617900503708,
-+                18662635732583, 2232324307922098
-+#else
-+                58249865, 31335375, 28571665, 23398914, 66634396, 23448733,
-+                63307367, 278094, 23440562, 33264224
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1853931367696942, 8107973870707, 350214504129299,
-+                775206934582587, 1752317649166792
-+#else
-+                10226222, 27625730, 15139955, 120818, 52241171, 5218602,
-+                32937275, 11551483, 50536904, 26111567
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1417148368003523, 721357181628282, 505725498207811,
-+                373232277872983, 261634707184480
-+#else
-+                17932739, 21117156, 43069306, 10749059, 11316803, 7535897,
-+                22503767, 5561594, 63462240, 3898660
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2186733281493267, 2250694917008620, 1014829812957440,
-+                479998161452389, 83566193876474
-+#else
-+                7749907, 32584865, 50769132, 33537967, 42090752, 15122142,
-+                65535333, 7152529, 21831162, 1245233
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1268116367301224, 560157088142809, 802626839600444,
-+                2210189936605713, 1129993785579988
-+#else
-+                26958440, 18896406, 4314585, 8346991, 61431100, 11960071,
-+                34519569, 32934396, 36706772, 16838219
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                615183387352312, 917611676109240, 878893615973325,
-+                978940963313282, 938686890583575
-+#else
-+                54942968, 9166946, 33491384, 13673479, 29787085, 13096535,
-+                6280834, 14587357, 44770839, 13987524
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                522024729211672, 1045059315315808, 1892245413707790,
-+                1907891107684253, 2059998109500714
-+#else
-+                42758936, 7778774, 21116000, 15572597, 62275598, 28196653,
-+                62807965, 28429792, 59639082, 30696363
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1799679152208884, 912132775900387, 25967768040979,
-+                432130448590461, 274568990261996
-+#else
-+                9681908, 26817309, 35157219, 13591837, 60225043, 386949,
-+                31622781, 6439245, 52527852, 4091396
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                98698809797682, 2144627600856209, 1907959298569602,
-+                811491302610148, 1262481774981493
-+#else
-+                58682418, 1470726, 38999185, 31957441, 3978626, 28430809,
-+                47486180, 12092162, 29077877, 18812444
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1791451399743152, 1713538728337276, 118349997257490,
-+                1882306388849954, 158235232210248
-+#else
-+                5269168, 26694706, 53878652, 25533716, 25932562, 1763552,
-+                61502754, 28048550, 47091016, 2357888
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1217809823321928, 2173947284933160, 1986927836272325,
-+                1388114931125539, 12686131160169
-+#else
-+                32264008, 18146780, 61721128, 32394338, 65017541, 29607531,
-+                23104803, 20684524, 5727337, 189038
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1650875518872272, 1136263858253897, 1732115601395988,
-+                734312880662190, 1252904681142109
-+#else
-+                14609104, 24599962, 61108297, 16931650, 52531476, 25810533,
-+                40363694, 10942114, 41219933, 18669734
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                372986456113865, 525430915458171, 2116279931702135,
-+                501422713587815, 1907002872974925
-+#else
-+                20513481, 5557931, 51504251, 7829530, 26413943, 31535028,
-+                45729895, 7471780, 13913677, 28416557
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                803147181835288, 868941437997146, 316299302989663,
-+                943495589630550, 571224287904572
-+#else
-+                41534488, 11967825, 29233242, 12948236, 60354399, 4713226,
-+                58167894, 14059179, 12878652, 8511905
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                227742695588364, 1776969298667369, 628602552821802,
-+                457210915378118, 2041906378111140
-+#else
-+                41452044, 3393630, 64153449, 26478905, 64858154, 9366907,
-+                36885446, 6812973, 5568676, 30426776
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                815000523470260, 913085688728307, 1052060118271173,
-+                1345536665214223, 541623413135555
-+#else
-+                11630004, 12144454, 2116339, 13606037, 27378885, 15676917,
-+                49700111, 20050058, 52713667, 8070817
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1580216071604333, 1877997504342444, 857147161260913,
-+                703522726778478, 2182763974211603
-+#else
-+                27117677, 23547054, 35826092, 27984343, 1127281, 12772488,
-+                37262958, 10483305, 55556115, 32525717
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1870080310923419, 71988220958492, 1783225432016732,
-+                615915287105016, 1035570475990230
-+#else
-+                10637467, 27866368, 5674780, 1072708, 40765276, 26572129,
-+                65424888, 9177852, 39615702, 15431202
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                730987750830150, 857613889540280, 1083813157271766,
-+                1002817255970169, 1719228484436074
-+#else
-+                20525126, 10892566, 54366392, 12779442, 37615830, 16150074,
-+                38868345, 14943141, 52052074, 25618500
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                377616581647602, 1581980403078513, 804044118130621,
-+                2034382823044191, 643844048472185
-+#else
-+                37084402, 5626925, 66557297, 23573344, 753597, 11981191,
-+                25244767, 30314666, 63752313, 9594023
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                176957326463017, 1573744060478586, 528642225008045,
-+                1816109618372371, 1515140189765006
-+#else
-+                43356201, 2636869, 61944954, 23450613, 585133, 7877383,
-+                11345683, 27062142, 13352334, 22577348
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1888911448245718, 1387110895611080, 1924503794066429,
-+                1731539523700949, 2230378382645454
-+#else
-+                65177046, 28146973, 3304648, 20669563, 17015805, 28677341,
-+                37325013, 25801949, 53893326, 33235227
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                443392177002051, 233793396845137, 2199506622312416,
-+                1011858706515937, 974676837063129
-+#else
-+                20239939, 6607058, 6203985, 3483793, 48721888, 32775202,
-+                46385121, 15077869, 44358105, 14523816
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1846351103143623, 1949984838808427, 671247021915253,
-+                1946756846184401, 1929296930380217
-+#else
-+                27406023, 27512775, 27423595, 29057038, 4996213, 10002360,
-+                38266833, 29008937, 36936121, 28748764
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                849646212452002, 1410198775302919, 73767886183695,
-+                1641663456615812, 762256272452411
-+#else
-+                11374242, 12660715, 17861383, 21013599, 10935567, 1099227,
-+                53222788, 24462691, 39381819, 11358503
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                692017667358279, 723305578826727, 1638042139863265,
-+                748219305990306, 334589200523901
-+#else
-+                54378055, 10311866, 1510375, 10778093, 64989409, 24408729,
-+                32676002, 11149336, 40985213, 4985767
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                22893968530686, 2235758574399251, 1661465835630252,
-+                925707319443452, 1203475116966621
-+#else
-+                48012542, 341146, 60911379, 33315398, 15756972, 24757770,
-+                66125820, 13794113, 47694557, 17933176
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                801299035785166, 1733292596726131, 1664508947088596,
-+                467749120991922, 1647498584535623
-+#else
-+                6490062, 11940286, 25495923, 25828072, 8668372, 24803116,
-+                3367602, 6970005, 65417799, 24549641
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                903105258014366, 427141894933047, 561187017169777,
-+                1884330244401954, 1914145708422219
-+#else
-+                1656478, 13457317, 15370807, 6364910, 13605745, 8362338,
-+                47934242, 28078708, 50312267, 28522993
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1344191060517578, 1960935031767890, 1518838929955259,
-+                1781502350597190, 1564784025565682
-+#else
-+                44835530, 20030007, 67044178, 29220208, 48503227, 22632463,
-+                46537798, 26546453, 67009010, 23317098
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                673723351748086, 1979969272514923, 1175287312495508,
-+                1187589090978666, 1881897672213940
-+#else
-+                17747446, 10039260, 19368299, 29503841, 46478228, 17513145,
-+                31992682, 17696456, 37848500, 28042460
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1917185587363432, 1098342571752737, 5935801044414,
-+                2000527662351839, 1538640296181569
-+#else
-+                31932008, 28568291, 47496481, 16366579, 22023614, 88450,
-+                11371999, 29810185, 4882241, 22927527
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2495540013192, 678856913479236, 224998292422872,
-+                219635787698590, 1972465269000940
-+#else
-+                29796488, 37186, 19818052, 10115756, 55279832, 3352735,
-+                18551198, 3272828, 61917932, 29392022
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                271413961212179, 1353052061471651, 344711291283483,
-+                2014925838520662, 2006221033113941
-+#else
-+                12501267, 4044383, 58495907, 20162046, 34678811, 5136598,
-+                47878486, 30024734, 330069, 29895023
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                194583029968109, 514316781467765, 829677956235672,
-+                1676415686873082, 810104584395840
-+#else
-+                6384877, 2899513, 17807477, 7663917, 64749976, 12363164,
-+                25366522, 24980540, 66837568, 12071498
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1980510813313589, 1948645276483975, 152063780665900,
-+                129968026417582, 256984195613935
-+#else
-+                58743349, 29511910, 25133447, 29037077, 60897836, 2265926,
-+                34339246, 1936674, 61949167, 3829362
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1860190562533102, 1936576191345085, 461100292705964,
-+                1811043097042830, 957486749306835
-+#else
-+                28425966, 27718999, 66531773, 28857233, 52891308, 6870929,
-+                7921550, 26986645, 26333139, 14267664
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                796664815624365, 1543160838872951, 1500897791837765,
-+                1667315977988401, 599303877030711
-+#else
-+                56041645, 11871230, 27385719, 22994888, 62522949, 22365119,
-+                10004785, 24844944, 45347639, 8930323
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1151480509533204, 2136010406720455, 738796060240027,
-+                319298003765044, 1150614464349587
-+#else
-+                45911060, 17158396, 25654215, 31829035, 12282011, 11008919,
-+                1541940, 4757911, 40617363, 17145491
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1731069268103150, 735642447616087, 1364750481334268,
-+                417232839982871, 927108269127661
-+#else
-+                13537262, 25794942, 46504023, 10961926, 61186044, 20336366,
-+                53952279, 6217253, 51165165, 13814989
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1017222050227968, 1987716148359, 2234319589635701,
-+                621282683093392, 2132553131763026
-+#else
-+                49686272, 15157789, 18705543, 29619, 24409717, 33293956,
-+                27361680, 9257833, 65152338, 31777517
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1567828528453324, 1017807205202360, 565295260895298,
-+                829541698429100, 307243822276582
-+#else
-+                42063564, 23362465, 15366584, 15166509, 54003778, 8423555,
-+                37937324, 12361134, 48422886, 4578289
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                249079270936248, 1501514259790706, 947909724204848,
-+                944551802437487, 552658763982480
-+#else
-+                24579768, 3711570, 1342322, 22374306, 40103728, 14124955,
-+                44564335, 14074918, 21964432, 8235257
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2089966982947227, 1854140343916181, 2151980759220007,
-+                2139781292261749, 158070445864917
-+#else
-+                60580251, 31142934, 9442965, 27628844, 12025639, 32067012,
-+                64127349, 31885225, 13006805, 2355433
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1338766321464554, 1906702607371284, 1519569445519894,
-+                115384726262267, 1393058953390992
-+#else
-+                50803946, 19949172, 60476436, 28412082, 16974358, 22643349,
-+                27202043, 1719366, 1141648, 20758196
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1364621558265400, 1512388234908357, 1926731583198686,
-+                2041482526432505, 920401122333774
-+#else
-+                54244920, 20334445, 58790597, 22536340, 60298718, 28710537,
-+                13475065, 30420460, 32674894, 13715045
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1884844597333588, 601480070269079, 620203503079537,
-+                1079527400117915, 1202076693132015
-+#else
-+                11423316, 28086373, 32344215, 8962751, 24989809, 9241752,
-+                53843611, 16086211, 38367983, 17912338
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                840922919763324, 727955812569642, 1303406629750194,
-+                522898432152867, 294161410441865
-+#else
-+                65699196, 12530727, 60740138, 10847386, 19531186, 19422272,
-+                55399715, 7791793, 39862921, 4383346
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                353760790835310, 1598361541848743, 1122905698202299,
-+                1922533590158905, 419107700666580
-+#else
-+                38137966, 5271446, 65842855, 23817442, 54653627, 16732598,
-+                62246457, 28647982, 27193556, 6245191
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                359856369838236, 180914355488683, 861726472646627,
-+                218807937262986, 575626773232501
-+#else
-+                51914908, 5362277, 65324971, 2695833, 4960227, 12840725,
-+                23061898, 3260492, 22510453, 8577507
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                755467689082474, 909202735047934, 730078068932500,
-+                936309075711518, 2007798262842972
-+#else
-+                54476394, 11257345, 34415870, 13548176, 66387860, 10879010,
-+                31168030, 13952092, 37537372, 29918525
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1609384177904073, 362745185608627, 1335318541768201,
-+                800965770436248, 547877979267412
-+#else
-+                3877321, 23981693, 32416691, 5405324, 56104457, 19897796,
-+                3759768, 11935320, 5611860, 8164018
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                984339177776787, 815727786505884, 1645154585713747,
-+                1659074964378553, 1686601651984156
-+#else
-+                50833043, 14667796, 15906460, 12155291, 44997715, 24514713,
-+                32003001, 24722143, 5773084, 25132323
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1697863093781930, 599794399429786, 1104556219769607,
-+                830560774794755, 12812858601017
-+#else
-+                43320746, 25300131, 1950874, 8937633, 18686727, 16459170,
-+                66203139, 12376319, 31632953, 190926
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1168737550514982, 897832437380552, 463140296333799,
-+                302564600022547, 2008360505135501
-+#else
-+                42515238, 17415546, 58684872, 13378745, 14162407, 6901328,
-+                58820115, 4508563, 41767309, 29926903
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1856930662813910, 678090852002597, 1920179140755167,
-+                1259527833759868, 55540971895511
-+#else
-+                8884438, 27670423, 6023973, 10104341, 60227295, 28612898,
-+                18722940, 18768427, 65436375, 827624
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1158643631044921, 476554103621892, 178447851439725,
-+                1305025542653569, 103433927680625
-+#else
-+                34388281, 17265135, 34605316, 7101209, 13354605, 2659080,
-+                65308289, 19446395, 42230385, 1541285
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2176793111709008, 1576725716350391, 2009350167273523,
-+                2012390194631546, 2125297410909580
-+#else
-+                2901328, 32436745, 3880375, 23495044, 49487923, 29941650,
-+                45306746, 29986950, 20456844, 31669399
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                825403285195098, 2144208587560784, 1925552004644643,
-+                1915177840006985, 1015952128947864
-+#else
-+                27019610, 12299467, 53450576, 31951197, 54247203, 28692960,
-+                47568713, 28538373, 29439640, 15138866
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1807108316634472, 1534392066433717, 347342975407218,
-+                1153820745616376, 7375003497471
-+#else
-+                21536104, 26928012, 34661045, 22864223, 44700786, 5175813,
-+                61688824, 17193268, 7779327, 109896
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                983061001799725, 431211889901241, 2201903782961093,
-+                817393911064341, 2214616493042167
-+#else
-+                30279725, 14648750, 59063993, 6425557, 13639621, 32810923,
-+                28698389, 12180118, 23177719, 33000357
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                228567918409756, 865093958780220, 358083886450556,
-+                159617889659320, 1360637926292598
-+#else
-+                26572828, 3405927, 35407164, 12890904, 47843196, 5335865,
-+                60615096, 2378491, 4439158, 20275085
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                234147501399755, 2229469128637390, 2175289352258889,
-+                1397401514549353, 1885288963089922
-+#else
-+                44392139, 3489069, 57883598, 33221678, 18875721, 32414337,
-+                14819433, 20822905, 49391106, 28092994
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1111762412951562, 252849572507389, 1048714233823341,
-+                146111095601446, 1237505378776770
-+#else
-+                62052362, 16566550, 15953661, 3767752, 56672365, 15627059,
-+                66287910, 2177224, 8550082, 18440267
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1113790697840279, 1051167139966244, 1045930658550944,
-+                2011366241542643, 1686166824620755
-+#else
-+                48635543, 16596774, 66727204, 15663610, 22860960, 15585581,
-+                39264755, 29971692, 43848403, 25125843
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1054097349305049, 1872495070333352, 182121071220717,
-+                1064378906787311, 100273572924182
-+#else
-+                34628313, 15707274, 58902952, 27902350, 29464557, 2713815,
-+                44383727, 15860481, 45206294, 1494192
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1306410853171605, 1627717417672447, 50983221088417,
-+                1109249951172250, 870201789081392
-+#else
-+                47546773, 19467038, 41524991, 24254879, 13127841, 759709,
-+                21923482, 16529112, 8742704, 12967017
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                104233794644221, 1548919791188248, 2224541913267306,
-+                2054909377116478, 1043803389015153
-+#else
-+                38643965, 1553204, 32536856, 23080703, 42417258, 33148257,
-+                58194238, 30620535, 37205105, 15553882
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                216762189468802, 707284285441622, 190678557969733,
-+                973969342604308, 1403009538434867
-+#else
-+                21877890, 3230008, 9881174, 10539357, 62311749, 2841331,
-+                11543572, 14513274, 19375923, 20906471
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1279024291038477, 344776835218310, 273722096017199,
-+                1834200436811442, 634517197663804
-+#else
-+                8832269, 19058947, 13253510, 5137575, 5037871, 4078777,
-+                24880818, 27331716, 2862652, 9455043
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                343805853118335, 1302216857414201, 566872543223541,
-+                2051138939539004, 321428858384280
-+#else
-+                29306751, 5123106, 20245049, 19404543, 9592565, 8447059,
-+                65031740, 30564351, 15511448, 4789663
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                470067171324852, 1618629234173951, 2000092177515639,
-+                7307679772789, 1117521120249968
-+#else
-+                46429108, 7004546, 8824831, 24119455, 63063159, 29803695,
-+                61354101, 108892, 23513200, 16652362
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                278151578291475, 1810282338562947, 1771599529530998,
-+                1383659409671631, 685373414471841
-+#else
-+                33852691, 4144781, 62632835, 26975308, 10770038, 26398890,
-+                60458447, 20618131, 48789665, 10212859
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                577009397403102, 1791440261786291, 2177643735971638,
-+                174546149911960, 1412505077782326
-+#else
-+                2756062, 8598110, 7383731, 26694540, 22312758, 32449420,
-+                21179800, 2600940, 57120566, 21047965
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                893719721537457, 1201282458018197, 1522349501711173,
-+                58011597740583, 1130406465887139
-+#else
-+                42463153, 13317461, 36659605, 17900503, 21365573, 22684775,
-+                11344423, 864440, 64609187, 16844368
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                412607348255453, 1280455764199780, 2233277987330768,
-+                14180080401665, 331584698417165
-+#else
-+                40676061, 6148328, 49924452, 19080277, 18782928, 33278435,
-+                44547329, 211299, 2719757, 4940997
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                262483770854550, 990511055108216, 526885552771698,
-+                571664396646158, 354086190278723
-+#else
-+                65784982, 3911312, 60160120, 14759764, 37081714, 7851206,
-+                21690126, 8518463, 26699843, 5276295
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1820352417585487, 24495617171480, 1547899057533253,
-+                10041836186225, 480457105094042
-+#else
-+                53958991, 27125364, 9396248, 365013, 24703301, 23065493,
-+                1321585, 149635, 51656090, 7159368
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2023310314989233, 637905337525881, 2106474638900687,
-+                557820711084072, 1687858215057826
-+#else
-+                9987761, 30149673, 17507961, 9505530, 9731535, 31388918,
-+                22356008, 8312176, 22477218, 25151047
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1144168702609745, 604444390410187, 1544541121756138,
-+                1925315550126027, 626401428894002
-+#else
-+                18155857, 17049442, 19744715, 9006923, 15154154, 23015456,
-+                24256459, 28689437, 44560690, 9334108
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1922168257351784, 2018674099908659, 1776454117494445,
-+                956539191509034, 36031129147635
-+#else
-+                2986088, 28642539, 10776627, 30080588, 10620589, 26471229,
-+                45695018, 14253544, 44521715, 536905
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                544644538748041, 1039872944430374, 876750409130610,
-+                710657711326551, 1216952687484972
-+#else
-+                4377737, 8115836, 24567078, 15495314, 11625074, 13064599,
-+                7390551, 10589625, 10838060, 18134008
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                58242421545916, 2035812695641843, 2118491866122923,
-+                1191684463816273, 46921517454099
-+#else
-+                47766460, 867879, 9277171, 30335973, 52677291, 31567988,
-+                19295825, 17757482, 6378259, 699185
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                272268252444639, 1374166457774292, 2230115177009552,
-+                1053149803909880, 1354288411641016
-+#else
-+                7895007, 4057113, 60027092, 20476675, 49222032, 33231305,
-+                66392824, 15693154, 62063800, 20180469
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1857910905368338, 1754729879288912, 885945464109877,
-+                1516096106802166, 1602902393369811
-+#else
-+                59371282, 27685029, 52542544, 26147512, 11385653, 13201616,
-+                31730678, 22591592, 63190227, 23885106
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1193437069800958, 901107149704790, 999672920611411,
-+                477584824802207, 364239578697845
-+#else
-+                10188286, 17783598, 59772502, 13427542, 22223443, 14896287,
-+                30743455, 7116568, 45322357, 5427592
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                886299989548838, 1538292895758047, 1590564179491896,
-+                1944527126709657, 837344427345298
-+#else
-+                696102, 13206899, 27047647, 22922350, 15285304, 23701253,
-+                10798489, 28975712, 19236242, 12477404
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                754558365378305, 1712186480903618, 1703656826337531,
-+                750310918489786, 518996040250900
-+#else
-+                55879425, 11243795, 50054594, 25513566, 66320635, 25386464,
-+                63211194, 11180503, 43939348, 7733643
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1309847803895382, 1462151862813074, 211370866671570,
-+                1544595152703681, 1027691798954090
-+#else
-+                17800790, 19518253, 40108434, 21787760, 23887826, 3149671,
-+                23466177, 23016261, 10322026, 15313801
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                803217563745370, 1884799722343599, 1357706345069218,
-+                2244955901722095, 730869460037413
-+#else
-+                26246234, 11968874, 32263343, 28085704, 6830754, 20231401,
-+                51314159, 33452449, 42659621, 10890803
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                689299471295966, 1831210565161071, 1375187341585438,
-+                1106284977546171, 1893781834054269
-+#else
-+                35743198, 10271362, 54448239, 27287163, 16690206, 20491888,
-+                52126651, 16484930, 25180797, 28219548
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                696351368613042, 1494385251239250, 738037133616932,
-+                636385507851544, 927483222611406
-+#else
-+                66522290, 10376443, 34522450, 22268075, 19801892, 10997610,
-+                2276632, 9482883, 316878, 13820577
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1949114198209333, 1104419699537997, 783495707664463,
-+                1747473107602770, 2002634765788641
-+#else
-+                57226037, 29044064, 64993357, 16457135, 56008783, 11674995,
-+                30756178, 26039378, 30696929, 29841583
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1607325776830197, 530883941415333, 1451089452727895,
-+                1581691157083423, 496100432831154
-+#else
-+                32988917, 23951020, 12499365, 7910787, 56491607, 21622917,
-+                59766047, 23569034, 34759346, 7392472
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1068900648804224, 2006891997072550, 1134049269345549,
-+                1638760646180091, 2055396084625778
-+#else
-+                58253184, 15927860, 9866406, 29905021, 64711949, 16898650,
-+                36699387, 24419436, 25112946, 30627788
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2222475519314561, 1870703901472013, 1884051508440561,
-+                1344072275216753, 1318025677799069
-+#else
-+                64604801, 33117465, 25621773, 27875660, 15085041, 28074555,
-+                42223985, 20028237, 5537437, 19640113
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                155711679280656, 681100400509288, 389811735211209,
-+                2135723811340709, 408733211204125
-+#else
-+                55883280, 2320284, 57524584, 10149186, 33664201, 5808647,
-+                52232613, 31824764, 31234589, 6090599
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                7813206966729, 194444201427550, 2071405409526507,
-+                1065605076176312, 1645486789731291
-+#else
-+                57475529, 116425, 26083934, 2897444, 60744427, 30866345, 609720,
-+                15878753, 60138459, 24519663
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                16625790644959, 1647648827778410, 1579910185572704,
-+                436452271048548, 121070048451050
-+#else
-+                39351007, 247743, 51914090, 24551880, 23288160, 23542496,
-+                43239268, 6503645, 20650474, 1804084
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1037263028552531, 568385780377829, 297953104144430,
-+                1558584511931211, 2238221839292471
-+#else
-+                39519059, 15456423, 8972517, 8469608, 15640622, 4439847,
-+                3121995, 23224719, 27842615, 33352104
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                190565267697443, 672855706028058, 338796554369226,
-+                337687268493904, 853246848691734
-+#else
-+                51801891, 2839643, 22530074, 10026331, 4602058, 5048462,
-+                28248656, 5031932, 55733782, 12714368
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1763863028400139, 766498079432444, 1321118624818005,
-+                69494294452268, 858786744165651
-+#else
-+                20807691, 26283607, 29286140, 11421711, 39232341, 19686201,
-+                45881388, 1035545, 47375635, 12796919
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1292056768563024, 1456632109855638, 1100631247050184,
-+                1386133165675321, 1232898350193752
-+#else
-+                12076880, 19253146, 58323862, 21705509, 42096072, 16400683,
-+                49517369, 20654993, 3480664, 18371617
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                366253102478259, 525676242508811, 1449610995265438,
-+                1183300845322183, 185960306491545
-+#else
-+                34747315, 5457596, 28548107, 7833186, 7303070, 21600887,
-+                42745799, 17632556, 33734809, 2771024
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                28315355815982, 460422265558930, 1799675876678724,
-+                1969256312504498, 1051823843138725
-+#else
-+                45719598, 421931, 26597266, 6860826, 22486084, 26817260,
-+                49971378, 29344205, 42556581, 15673396
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                156914999361983, 1606148405719949, 1665208410108430,
-+                317643278692271, 1383783705665320
-+#else
-+                46924223, 2338215, 19788685, 23933476, 63107598, 24813538,
-+                46837679, 4733253, 3727144, 20619984
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                54684536365732, 2210010038536222, 1194984798155308,
-+                535239027773705, 1516355079301361
-+#else
-+                6120100, 814863, 55314462, 32931715, 6812204, 17806661, 2019593,
-+                7975683, 31123697, 22595451
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1484387703771650, 198537510937949, 2186282186359116,
-+                617687444857508, 647477376402122
-+#else
-+                30069250, 22119100, 30434653, 2958439, 18399564, 32578143,
-+                12296868, 9204260, 50676426, 9648164
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2147715541830533, 500032538445817, 646380016884826,
-+                352227855331122, 1488268620408052
-+#else
-+                32705413, 32003455, 30705657, 7451065, 55303258, 9631812,
-+                3305266, 5248604, 41100532, 22176930
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                159386186465542, 1877626593362941, 618737197060512,
-+                1026674284330807, 1158121760792685
-+#else
-+                17219846, 2375039, 35537917, 27978816, 47649184, 9219902,
-+                294711, 15298639, 2662509, 17257359
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1744544377739822, 1964054180355661, 1685781755873170,
-+                2169740670377448, 1286112621104591
-+#else
-+                65935918, 25995736, 62742093, 29266687, 45762450, 25120105,
-+                32087528, 32331655, 32247247, 19164571
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                81977249784993, 1667943117713086, 1668983819634866,
-+                1605016835177615, 1353960708075544
-+#else
-+                14312609, 1221556, 17395390, 24854289, 62163122, 24869796,
-+                38911119, 23916614, 51081240, 20175586
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1602253788689063, 439542044889886, 2220348297664483,
-+                657877410752869, 157451572512238
-+#else
-+                65680039, 23875441, 57873182, 6549686, 59725795, 33085767,
-+                23046501, 9803137, 17597934, 2346211
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1029287186166717, 65860128430192, 525298368814832,
-+                1491902500801986, 1461064796385400
-+#else
-+                18510781, 15337574, 26171504, 981392, 44867312, 7827555,
-+                43617730, 22231079, 3059832, 21771562
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                408216988729246, 2121095722306989, 913562102267595,
-+                1879708920318308, 241061448436731
-+#else
-+                10141598, 6082907, 17829293, 31606789, 9830091, 13613136,
-+                41552228, 28009845, 33606651, 3592095
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1185483484383269, 1356339572588553, 584932367316448,
-+                102132779946470, 1792922621116791
-+#else
-+                33114149, 17665080, 40583177, 20211034, 33076704, 8716171,
-+                1151462, 1521897, 66126199, 26716628
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1966196870701923, 2230044620318636, 1425982460745905,
-+                261167817826569, 46517743394330
-+#else
-+                34169699, 29298616, 23947180, 33230254, 34035889, 21248794,
-+                50471177, 3891703, 26353178, 693168
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                107077591595359, 884959942172345, 27306869797400,
-+                2224911448949390, 964352058245223
-+#else
-+                30374239, 1595580, 50224825, 13186930, 4600344, 406904, 9585294,
-+                33153764, 31375463, 14369965
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1730194207717538, 431790042319772, 1831515233279467,
-+                1372080552768581, 1074513929381760
-+#else
-+                52738210, 25781902, 1510300, 6434173, 48324075, 27291703,
-+                32732229, 20445593, 17901440, 16011505
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1450880638731607, 1019861580989005, 1229729455116861,
-+                1174945729836143, 826083146840706
-+#else
-+                18171223, 21619806, 54608461, 15197121, 56070717, 18324396,
-+                47936623, 17508055, 8764034, 12309598
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1899935429242705, 1602068751520477, 940583196550370,
-+                82431069053859, 1540863155745696
-+#else
-+                5975889, 28311244, 47649501, 23872684, 55567586, 14015781,
-+                43443107, 1228318, 17544096, 22960650
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2136688454840028, 2099509000964294, 1690800495246475,
-+                1217643678575476, 828720645084218
-+#else
-+                5811932, 31839139, 3442886, 31285122, 48741515, 25194890,
-+                49064820, 18144304, 61543482, 12348899
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                765548025667841, 462473984016099, 998061409979798,
-+                546353034089527, 2212508972466858
-+#else
-+                35709185, 11407554, 25755363, 6891399, 63851926, 14872273,
-+                42259511, 8141294, 56476330, 32968952
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                46575283771160, 892570971573071, 1281983193144090,
-+                1491520128287375, 75847005908304
-+#else
-+                54433560, 694025, 62032719, 13300343, 14015258, 19103038,
-+                57410191, 22225381, 30944592, 1130208
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1801436127943107, 1734436817907890, 1268728090345068,
-+                167003097070711, 2233597765834956
-+#else
-+                8247747, 26843490, 40546482, 25845122, 52706924, 18905521,
-+                4652151, 2488540, 23550156, 33283200
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1997562060465113, 1048700225534011, 7615603985628,
-+                1855310849546841, 2242557647635213
-+#else
-+                17294297, 29765994, 7026747, 15626851, 22990044, 113481,
-+                2267737, 27646286, 66700045, 33416712
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1161017320376250, 492624580169043, 2169815802355237,
-+                976496781732542, 1770879511019629
-+#else
-+                16091066, 17300506, 18599251, 7340678, 2137637, 32332775,
-+                63744702, 14550935, 3260525, 26388161
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1357044908364776, 729130645262438, 1762469072918979,
-+                1365633616878458, 181282906404941
-+#else
-+                62198760, 20221544, 18550886, 10864893, 50649539, 26262835,
-+                44079994, 20349526, 54360141, 2701325
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1080413443139865, 1155205815510486, 1848782073549786,
-+                622566975152580, 124965574467971
-+#else
-+                58534169, 16099414, 4629974, 17213908, 46322650, 27548999,
-+                57090500, 9276970, 11329923, 1862132
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1184526762066993, 247622751762817, 692129017206356,
-+                820018689412496, 2188697339828085
-+#else
-+                14763057, 17650824, 36190593, 3689866, 3511892, 10313526,
-+                45157776, 12219230, 58070901, 32614131
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2020536369003019, 202261491735136, 1053169669150884,
-+                2056531979272544, 778165514694311
-+#else
-+                8894987, 30108338, 6150752, 3013931, 301220, 15693451, 35127648,
-+                30644714, 51670695, 11595569
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                237404399610207, 1308324858405118, 1229680749538400,
-+                720131409105291, 1958958863624906
-+#else
-+                15214943, 3537601, 40870142, 19495559, 4418656, 18323671,
-+                13947275, 10730794, 53619402, 29190761
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                515583508038846, 17656978857189, 1717918437373989,
-+                1568052070792483, 46975803123923
-+#else
-+                64570558, 7682792, 32759013, 263109, 37124133, 25598979,
-+                44776739, 23365796, 977107, 699994
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                281527309158085, 36970532401524, 866906920877543,
-+                2222282602952734, 1289598729589882
-+#else
-+                54642373, 4195083, 57897332, 550903, 51543527, 12917919,
-+                19118110, 33114591, 36574330, 19216518
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1278207464902042, 494742455008756, 1262082121427081,
-+                1577236621659884, 1888786707293291
-+#else
-+                31788442, 19046775, 4799988, 7372237, 8808585, 18806489,
-+                9408236, 23502657, 12493931, 28145115
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                353042527954210, 1830056151907359, 1111731275799225,
-+                174960955838824, 404312815582675
-+#else
-+                41428258, 5260743, 47873055, 27269961, 63412921, 16566086,
-+                27218280, 2607121, 29375955, 6024730
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2064251142068628, 1666421603389706, 1419271365315441,
-+                468767774902855, 191535130366583
-+#else
-+                842132, 30759739, 62345482, 24831616, 26332017, 21148791,
-+                11831879, 6985184, 57168503, 2854095
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1716987058588002, 1859366439773457, 1767194234188234,
-+                64476199777924, 1117233614485261
-+#else
-+                62261602, 25585100, 2516241, 27706719, 9695690, 26333246,
-+                16512644, 960770, 12121869, 16648078
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                984292135520292, 135138246951259, 2220652137473167,
-+                1722843421165029, 190482558012909
-+#else
-+                51890212, 14667095, 53772635, 2013716, 30598287, 33090295,
-+                35603941, 25672367, 20237805, 2838411
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                298845952651262, 1166086588952562, 1179896526238434,
-+                1347812759398693, 1412945390096208
-+#else
-+                47820798, 4453151, 15298546, 17376044, 22115042, 17581828,
-+                12544293, 20083975, 1068880, 21054527
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1143239552672925, 906436640714209, 2177000572812152,
-+                2075299936108548, 325186347798433
-+#else
-+                57549981, 17035596, 33238497, 13506958, 30505848, 32439836,
-+                58621956, 30924378, 12521377, 4845654
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                721024854374772, 684487861263316, 1373438744094159,
-+                2193186935276995, 1387043709851261
-+#else
-+                38910324, 10744107, 64150484, 10199663, 7759311, 20465832,
-+                3409347, 32681032, 60626557, 20668561
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                418098668140962, 715065997721283, 1471916138376055,
-+                2168570337288357, 937812682637044
-+#else
-+                43547042, 6230155, 46726851, 10655313, 43068279, 21933259,
-+                10477733, 32314216, 63995636, 13974497
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1043584187226485, 2143395746619356, 2209558562919611,
-+                482427979307092, 847556718384018
-+#else
-+                12966261, 15550616, 35069916, 31939085, 21025979, 32924988,
-+                5642324, 7188737, 18895762, 12629579
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1248731221520759, 1465200936117687, 540803492710140,
-+                52978634680892, 261434490176109
-+#else
-+                14741879, 18607545, 22177207, 21833195, 1279740, 8058600,
-+                11758140, 789443, 32195181, 3895677
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1057329623869501, 620334067429122, 461700859268034,
-+                2012481616501857, 297268569108938
-+#else
-+                10758205, 15755439, 62598914, 9243697, 62229442, 6879878,
-+                64904289, 29988312, 58126794, 4429646
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1055352180870759, 1553151421852298, 1510903185371259,
-+                1470458349428097, 1226259419062731
-+#else
-+                64654951, 15725972, 46672522, 23143759, 61304955, 22514211,
-+                59972993, 21911536, 18047435, 18272689
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1492988790301668, 790326625573331, 1190107028409745,
-+                1389394752159193, 1620408196604194
-+#else
-+                41935844, 22247266, 29759955, 11776784, 44846481, 17733976,
-+                10993113, 20703595, 49488162, 24145963
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                47000654413729, 1004754424173864, 1868044813557703,
-+                173236934059409, 588771199737015
-+#else
-+                21987233, 700364, 42603816, 14972007, 59334599, 27836036,
-+                32155025, 2581431, 37149879, 8773374
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                30498470091663, 1082245510489825, 576771653181956,
-+                806509986132686, 1317634017056939
-+#else
-+                41540495, 454462, 53896929, 16126714, 25240068, 8594567,
-+                20656846, 12017935, 59234475, 19634276
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                420308055751555, 1493354863316002, 165206721528088,
-+                1884845694919786, 2065456951573059
-+#else
-+                6028163, 6263078, 36097058, 22252721, 66289944, 2461771,
-+                35267690, 28086389, 65387075, 30777706
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1115636332012334, 1854340990964155, 83792697369514,
-+                1972177451994021, 457455116057587
-+#else
-+                54829870, 16624276, 987579, 27631834, 32908202, 1248608,
-+                7719845, 29387734, 28408819, 6816612
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1698968457310898, 1435137169051090, 1083661677032510,
-+                938363267483709, 340103887207182
-+#else
-+                56750770, 25316602, 19549650, 21385210, 22082622, 16147817,
-+                20613181, 13982702, 56769294, 5067942
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1995325341336574, 911500251774648, 164010755403692,
-+                855378419194762, 1573601397528842
-+#else
-+                36602878, 29732664, 12074680, 13582412, 47230892, 2443950,
-+                47389578, 12746131, 5331210, 23448488
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                241719380661528, 310028521317150, 1215881323380194,
-+                1408214976493624, 2141142156467363
-+#else
-+                30528792, 3601899, 65151774, 4619784, 39747042, 18118043,
-+                24180792, 20984038, 27679907, 31905504
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1315157046163473, 727368447885818, 1363466668108618,
-+                1668921439990361, 1398483384337907
-+#else
-+                9402385, 19597367, 32834042, 10838634, 40528714, 20317236,
-+                26653273, 24868867, 22611443, 20839026
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                75029678299646, 1015388206460473, 1849729037055212,
-+                1939814616452984, 444404230394954
-+#else
-+                22190590, 1118029, 22736441, 15130463, 36648172, 27563110,
-+                19189624, 28905490, 4854858, 6622139
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2053597130993710, 2024431685856332, 2233550957004860,
-+                2012407275509545, 872546993104440
-+#else
-+                58798126, 30600981, 58846284, 30166382, 56707132, 33282502,
-+                13424425, 29987205, 26404408, 13001963
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1217269667678610, 599909351968693, 1390077048548598,
-+                1471879360694802, 739586172317596
-+#else
-+                35867026, 18138731, 64114613, 8939345, 11562230, 20713762,
-+                41044498, 21932711, 51703708, 11020692
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1718318639380794, 1560510726633958, 904462881159922,
-+                1418028351780052, 94404349451937
-+#else
-+                1866042, 25604943, 59210214, 23253421, 12483314, 13477547,
-+                3175636, 21130269, 28761761, 1406734
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2132502667405250, 214379346175414, 1502748313768060,
-+                1960071701057800, 1353971822643138
-+#else
-+                66660290, 31776765, 13018550, 3194501, 57528444, 22392694,
-+                24760584, 29207344, 25577410, 20175752
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                319394212043702, 2127459436033571, 717646691535162,
-+                663366796076914, 318459064945314
-+#else
-+                42818486, 4759344, 66418211, 31701615, 2066746, 10693769,
-+                37513074, 9884935, 57739938, 4745409
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                405989424923593, 1960452633787083, 667349034401665,
-+                1492674260767112, 1451061489880787
-+#else
-+                57967561, 6049713, 47577803, 29213020, 35848065, 9944275,
-+                51646856, 22242579, 10931923, 21622501
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                947085906234007, 323284730494107, 1485778563977200,
-+                728576821512394, 901584347702286
-+#else
-+                50547351, 14112679, 59096219, 4817317, 59068400, 22139825,
-+                44255434, 10856640, 46638094, 13434653
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1575783124125742, 2126210792434375, 1569430791264065,
-+                1402582372904727, 1891780248341114
-+#else
-+                22759470, 23480998, 50342599, 31683009, 13637441, 23386341,
-+                1765143, 20900106, 28445306, 28189722
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                838432205560695, 1997703511451664, 1018791879907867,
-+                1662001808174331, 78328132957753
-+#else
-+                29875063, 12493613, 2795536, 29768102, 1710619, 15181182,
-+                56913147, 24765756, 9074233, 1167180
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                739152638255629, 2074935399403557, 505483666745895,
-+                1611883356514088, 628654635394878
-+#else
-+                40903181, 11014232, 57266213, 30918946, 40200743, 7532293,
-+                48391976, 24018933, 3843902, 9367684
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1822054032121349, 643057948186973, 7306757352712,
-+                577249257962099, 284735863382083
-+#else
-+                56139269, 27150720, 9591133, 9582310, 11349256, 108879,
-+                16235123, 8601684, 66969667, 4242894
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1366558556363930, 1448606567552086, 1478881020944768,
-+                165803179355898, 1115718458123498
-+#else
-+                22092954, 20363309, 65066070, 21585919, 32186752, 22037044,
-+                60534522, 2470659, 39691498, 16625500
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                204146226972102, 1630511199034723, 2215235214174763,
-+                174665910283542, 956127674017216
-+#else
-+                56051142, 3042015, 13770083, 24296510, 584235, 33009577,
-+                59338006, 2602724, 39757248, 14247412
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1562934578796716, 1070893489712745, 11324610642270,
-+                958989751581897, 2172552325473805
-+#else
-+                6314156, 23289540, 34336361, 15957556, 56951134, 168749,
-+                58490057, 14290060, 27108877, 32373552
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1770564423056027, 735523631664565, 1326060113795289,
-+                1509650369341127, 65892421582684
-+#else
-+                58522267, 26383465, 13241781, 10960156, 34117849, 19759835,
-+                33547975, 22495543, 39960412, 981873
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                623682558650637, 1337866509471512, 990313350206649,
-+                1314236615762469, 1164772974270275
-+#else
-+                22833421, 9293594, 34459416, 19935764, 57971897, 14756818,
-+                44180005, 19583651, 56629059, 17356469
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                223256821462517, 723690150104139, 1000261663630601,
-+                933280913953265, 254872671543046
-+#else
-+                59340277, 3326785, 38997067, 10783823, 19178761, 14905060,
-+                22680049, 13906969, 51175174, 3797898
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1969087237026041, 624795725447124, 1335555107635969,
-+                2069986355593023, 1712100149341902
-+#else
-+                21721337, 29341686, 54902740, 9310181, 63226625, 19901321,
-+                23740223, 30845200, 20491982, 25512280
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1236103475266979, 1837885883267218, 1026072585230455,
-+                1025865513954973, 1801964901432134
-+#else
-+                9209251, 18419377, 53852306, 27386633, 66377847, 15289672,
-+                25947805, 15286587, 30997318, 26851369
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1115241013365517, 1712251818829143, 2148864332502771,
-+                2096001471438138, 2235017246626125
-+#else
-+                7392013, 16618386, 23946583, 25514540, 53843699, 32020573,
-+                52911418, 31232855, 17649997, 33304352
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1299268198601632, 2047148477845621, 2165648650132450,
-+                1612539282026145, 514197911628890
-+#else
-+                57807776, 19360604, 30609525, 30504889, 41933794, 32270679,
-+                51867297, 24028707, 64875610, 7662145
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                118352772338543, 1067608711804704, 1434796676193498,
-+                1683240170548391, 230866769907437
-+#else
-+                49550191, 1763593, 33994528, 15908609, 37067994, 21380136,
-+                7335079, 25082233, 63934189, 3440182
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1850689576796636, 1601590730430274, 1139674615958142,
-+                1954384401440257, 76039205311
-+#else
-+                47219164, 27577423, 42997570, 23865561, 10799742, 16982475,
-+                40449, 29122597, 4862399, 1133
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1723387471374172, 997301467038410, 533927635123657,
-+                20928644693965, 1756575222802513
-+#else
-+                34252636, 25680474, 61686474, 14860949, 50789833, 7956141,
-+                7258061, 311861, 36513873, 26175010
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2146711623855116, 503278928021499, 625853062251406,
-+                1109121378393107, 1033853809911861
-+#else
-+                63335436, 31988495, 28985339, 7499440, 24445838, 9325937,
-+                29727763, 16527196, 18278453, 15405622
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                571005965509422, 2005213373292546, 1016697270349626,
-+                56607856974274, 914438579435146
-+#else
-+                62726958, 8508651, 47210498, 29880007, 61124410, 15149969,
-+                53795266, 843522, 45233802, 13626196
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1346698876211176, 2076651707527589, 1084761571110205,
-+                265334478828406, 1068954492309671
-+#else
-+                2281448, 20067377, 56193445, 30944521, 1879357, 16164207,
-+                56324982, 3953791, 13340839, 15928663
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1769967932677654, 1695893319756416, 1151863389675920,
-+                1781042784397689, 400287774418285
-+#else
-+                31727126, 26374577, 48671360, 25270779, 2875792, 17164102,
-+                41838969, 26539605, 43656557, 5964752
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1851867764003121, 403841933237558, 820549523771987,
-+                761292590207581, 1743735048551143
-+#else
-+                4100401, 27594980, 49929526, 6017713, 48403027, 12227140,
-+                40424029, 11344143, 2538215, 25983677
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                410915148140008, 2107072311871739, 1004367461876503,
-+                99684895396761, 1180818713503224
-+#else
-+                57675240, 6123112, 11159803, 31397824, 30016279, 14966241,
-+                46633881, 1485420, 66479608, 17595569
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                285945406881439, 648174397347453, 1098403762631981,
-+                1366547441102991, 1505876883139217
-+#else
-+                40304287, 4260918, 11851389, 9658551, 35091757, 16367491,
-+                46903439, 20363143, 11659921, 22439314
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                672095903120153, 1675918957959872, 636236529315028,
-+                1569297300327696, 2164144194785875
-+#else
-+                26180377, 10015009, 36264640, 24973138, 5418196, 9480663,
-+                2231568, 23384352, 33100371, 32248261
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1902708175321798, 1035343530915438, 1178560808893263,
-+                301095684058146, 1280977479761118
-+#else
-+                15121094, 28352561, 56718958, 15427820, 39598927, 17561924,
-+                21670946, 4486675, 61177054, 19088051
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1615357281742403, 404257611616381, 2160201349780978,
-+                1160947379188955, 1578038619549541
-+#else
-+                16166467, 24070699, 56004733, 6023907, 35182066, 32189508,
-+                2340059, 17299464, 56373093, 23514607
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2013087639791217, 822734930507457, 1785668418619014,
-+                1668650702946164, 389450875221715
-+#else
-+                28042865, 29997343, 54982337, 12259705, 63391366, 26608532,
-+                6766452, 24864833, 18036435, 5803270
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                453918449698368, 106406819929001, 2072540975937135,
-+                308588860670238, 1304394580755385
-+#else
-+                66291264, 6763911, 11803561, 1585585, 10958447, 30883267,
-+                23855390, 4598332, 60949433, 19436993
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1295082798350326, 2091844511495996, 1851348972587817,
-+                3375039684596, 789440738712837
-+#else
-+                36077558, 19298237, 17332028, 31170912, 31312681, 27587249,
-+                696308, 50292, 47013125, 11763583
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2083069137186154, 848523102004566, 993982213589257,
-+                1405313299916317, 1532824818698468
-+#else
-+                66514282, 31040148, 34874710, 12643979, 12650761, 14811489,
-+                665117, 20940800, 47335652, 22840869
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1495961298852430, 1397203457344779, 1774950217066942,
-+                139302743555696, 66603584342787
-+#else
-+                30464590, 22291560, 62981387, 20819953, 19835326, 26448819,
-+                42712688, 2075772, 50088707, 992470
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1782411379088302, 1096724939964781, 27593390721418,
-+                542241850291353, 1540337798439873
-+#else
-+                18357166, 26559999, 7766381, 16342475, 37783946, 411173,
-+                14578841, 8080033, 55534529, 22952821
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                693543956581437, 171507720360750, 1557908942697227,
-+                1074697073443438, 1104093109037196
-+#else
-+                19598397, 10334610, 12555054, 2555664, 18821899, 23214652,
-+                21873262, 16014234, 26224780, 16452269
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                345288228393419, 1099643569747172, 134881908403743,
-+                1740551994106740, 248212179299770
-+#else
-+                36884939, 5145195, 5944548, 16385966, 3976735, 2009897,
-+                55731060, 25936245, 46575034, 3698649
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                231429562203065, 1526290236421172, 2021375064026423,
-+                1520954495658041, 806337791525116
-+#else
-+                14187449, 3448569, 56472628, 22743496, 44444983, 30120835,
-+                7268409, 22663988, 27394300, 12015369
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1079623667189886, 872403650198613, 766894200588288,
-+                2163700860774109, 2023464507911816
-+#else
-+                19695742, 16087646, 28032085, 12999827, 6817792, 11427614,
-+                20244189, 32241655, 53849736, 30151970
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                854645372543796, 1936406001954827, 151460662541253,
-+                825325739271555, 1554306377287556
-+#else
-+                30860084, 12735208, 65220619, 28854697, 50133957, 2256939,
-+                58942851, 12298311, 58558340, 23160969
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1497138821904622, 1044820250515590, 1742593886423484,
-+                1237204112746837, 849047450816987
-+#else
-+                61389038, 22309106, 65198214, 15569034, 26642876, 25966672,
-+                61319509, 18435777, 62132699, 12651792
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                667962773375330, 1897271816877105, 1399712621683474,
-+                1143302161683099, 2081798441209593
-+#else
-+                64260450, 9953420, 11531313, 28271553, 26895122, 20857343,
-+                53990043, 17036529, 9768697, 31021214
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                127147851567005, 1936114012888110, 1704424366552046,
-+                856674880716312, 716603621335359
-+#else
-+                42389405, 1894650, 66821166, 28850346, 15348718, 25397902,
-+                32767512, 12765450, 4940095, 10678226
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1072409664800960, 2146937497077528, 1508780108920651,
-+                935767602384853, 1112800433544068
-+#else
-+                18860224, 15980149, 48121624, 31991861, 40875851, 22482575,
-+                59264981, 13944023, 42736516, 16582018
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                333549023751292, 280219272863308, 2104176666454852,
-+                1036466864875785, 536135186520207
-+#else
-+                51604604, 4970267, 37215820, 4175592, 46115652, 31354675,
-+                55404809, 15444559, 56105103, 7989036
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                373666279883137, 146457241530109, 304116267127857,
-+                416088749147715, 1258577131183391
-+#else
-+                31490433, 5568061, 64696061, 2182382, 34772017, 4531685,
-+                35030595, 6200205, 47422751, 18754260
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1186115062588401, 2251609796968486, 1098944457878953,
-+                1153112761201374, 1791625503417267
-+#else
-+                49800177, 17674491, 35586086, 33551600, 34221481, 16375548,
-+                8680158, 17182719, 28550067, 26697300
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1870078460219737, 2129630962183380, 852283639691142,
-+                292865602592851, 401904317342226
-+#else
-+                38981977, 27866340, 16837844, 31733974, 60258182, 12700015,
-+                37068883, 4364037, 1155602, 5988841
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1361070124828035, 815664541425524, 1026798897364671,
-+                1951790935390647, 555874891834790
-+#else
-+                21890435, 20281525, 54484852, 12154348, 59276991, 15300495,
-+                23148983, 29083951, 24618406, 8283181
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1546301003424277, 459094500062839, 1097668518375311,
-+                1780297770129643, 720763293687608
-+#else
-+                33972757, 23041680, 9975415, 6841041, 35549071, 16356535,
-+                3070187, 26528504, 1466168, 10740210
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1212405311403990, 1536693382542438, 61028431067459,
-+                1863929423417129, 1223219538638038
-+#else
-+                65599446, 18066246, 53605478, 22898515, 32799043, 909394,
-+                53169961, 27774712, 34944214, 18227391
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1294303766540260, 1183557465955093, 882271357233093,
-+                63854569425375, 2213283684565087
-+#else
-+                3960804, 19286629, 39082773, 17636380, 47704005, 13146867,
-+                15567327, 951507, 63848543, 32980496
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                339050984211414, 601386726509773, 413735232134068,
-+                966191255137228, 1839475899458159
-+#else
-+                24740822, 5052253, 37014733, 8961360, 25877428, 6165135,
-+                42740684, 14397371, 59728495, 27410326
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                235605972169408, 2174055643032978, 1538335001838863,
-+                1281866796917192, 1815940222628465
-+#else
-+                38220480, 3510802, 39005586, 32395953, 55870735, 22922977,
-+                51667400, 19101303, 65483377, 27059617
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1632352921721536, 1833328609514701, 2092779091951987,
-+                1923956201873226, 2210068022482919
-+#else
-+                793280, 24323954, 8836301, 27318725, 39747955, 31184838,
-+                33152842, 28669181, 57202663, 32932579
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                35271216625062, 1712350667021807, 983664255668860,
-+                98571260373038, 1232645608559836
-+#else
-+                5666214, 525582, 20782575, 25516013, 42570364, 14657739,
-+                16099374, 1468826, 60937436, 18367850
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1998172393429622, 1798947921427073, 784387737563581,
-+                1589352214827263, 1589861734168180
-+#else
-+                62249590, 29775088, 64191105, 26806412, 7778749, 11688288,
-+                36704511, 23683193, 65549940, 23690785
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1733739258725305, 31715717059538, 201969945218860,
-+                992093044556990, 1194308773174556
-+#else
-+                10896313, 25834728, 824274, 472601, 47648556, 3009586, 25248958,
-+                14783338, 36527388, 17796587
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                846415389605137, 746163495539180, 829658752826080,
-+                592067705956946, 957242537821393
-+#else
-+                10566929, 12612572, 35164652, 11118702, 54475488, 12362878,
-+                21752402, 8822496, 24003793, 14264025
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1758148849754419, 619249044817679, 168089007997045,
-+                1371497636330523, 1867101418880350
-+#else
-+                27713843, 26198459, 56100623, 9227529, 27050101, 2504721,
-+                23886875, 20436907, 13958494, 27821979
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                326633984209635, 261759506071016, 1700682323676193,
-+                1577907266349064, 1217647663383016
-+#else
-+                43627235, 4867225, 39861736, 3900520, 29838369, 25342141,
-+                35219464, 23512650, 7340520, 18144364
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1714182387328607, 1477856482074168, 574895689942184,
-+                2159118410227270, 1555532449716575
-+#else
-+                4646495, 25543308, 44342840, 22021777, 23184552, 8566613,
-+                31366726, 32173371, 52042079, 23179239
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                853828206885131, 998498946036955, 1835887550391235,
-+                207627336608048, 258363815956050
-+#else
-+                49838347, 12723031, 50115803, 14878793, 21619651, 27356856,
-+                27584816, 3093888, 58265170, 3849920
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                141141474651677, 1236728744905256, 643101419899887,
-+                1646615130509173, 1208239602291765
-+#else
-+                58043933, 2103171, 25561640, 18428694, 61869039, 9582957,
-+                32477045, 24536477, 5002293, 18004173
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1501663228068911, 1354879465566912, 1444432675498247,
-+                897812463852601, 855062598754348
-+#else
-+                55051311, 22376525, 21115584, 20189277, 8808711, 21523724,
-+                16489529, 13378448, 41263148, 12741425
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                714380763546606, 1032824444965790, 1774073483745338,
-+                1063840874947367, 1738680636537158
-+#else
-+                61162478, 10645102, 36197278, 15390283, 63821882, 26435754,
-+                24306471, 15852464, 28834118, 25908360
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1640635546696252, 633168953192112, 2212651044092396,
-+                30590958583852, 368515260889378
-+#else
-+                49773116, 24447374, 42577584, 9434952, 58636780, 32971069,
-+                54018092, 455840, 20461858, 5491305
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1171650314802029, 1567085444565577, 1453660792008405,
-+                757914533009261, 1619511342778196
-+#else
-+                13669229, 17458950, 54626889, 23351392, 52539093, 21661233,
-+                42112877, 11293806, 38520660, 24132599
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                420958967093237, 971103481109486, 2169549185607107,
-+                1301191633558497, 1661514101014240
-+#else
-+                28497909, 6272777, 34085870, 14470569, 8906179, 32328802,
-+                18504673, 19389266, 29867744, 24758489
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                907123651818302, 1332556122804146, 1824055253424487,
-+                1367614217442959, 1982558335973172
-+#else
-+                50901822, 13517195, 39309234, 19856633, 24009063, 27180541,
-+                60741263, 20379039, 22853428, 29542421
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1121533090144639, 1021251337022187, 110469995947421,
-+                1511059774758394, 2110035908131662
-+#else
-+                24191359, 16712145, 53177067, 15217830, 14542237, 1646131,
-+                18603514, 22516545, 12876622, 31441985
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                303213233384524, 2061932261128138, 352862124777736,
-+                40828818670255, 249879468482660
-+#else
-+                17902668, 4518229, 66697162, 30725184, 26878216, 5258055,
-+                54248111, 608396, 16031844, 3723494
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                856559257852200, 508517664949010, 1378193767894916,
-+                1723459126947129, 1962275756614521
-+#else
-+                38476072, 12763727, 46662418, 7577503, 33001348, 20536687,
-+                17558841, 25681542, 23896953, 29240187
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1445691340537320, 40614383122127, 402104303144865,
-+                485134269878232, 1659439323587426
-+#else
-+                47103464, 21542479, 31520463, 605201, 2543521, 5991821,
-+                64163800, 7229063, 57189218, 24727572
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                20057458979482, 1183363722525800, 2140003847237215,
-+                2053873950687614, 2112017736174909
-+#else
-+                28816026, 298879, 38943848, 17633493, 19000927, 31888542,
-+                54428030, 30605106, 49057085, 31471516
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2228654250927986, 1483591363415267, 1368661293910956,
-+                1076511285177291, 526650682059608
-+#else
-+                16000882, 33209536, 3493091, 22107234, 37604268, 20394642,
-+                12577739, 16041268, 47393624, 7847706
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                709481497028540, 531682216165724, 316963769431931,
-+                1814315888453765, 258560242424104
-+#else
-+                10151868, 10572098, 27312476, 7922682, 14825339, 4723128,
-+                34252933, 27035413, 57088296, 3852847
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1053447823660455, 1955135194248683, 1010900954918985,
-+                1182614026976701, 1240051576966610
-+#else
-+                55678375, 15697595, 45987307, 29133784, 5386313, 15063598,
-+                16514493, 17622322, 29330898, 18478208
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1957943897155497, 1788667368028035, 137692910029106,
-+                1039519607062, 826404763313028
-+#else
-+                41609129, 29175637, 51885955, 26653220, 16615730, 2051784,
-+                3303702, 15490, 39560068, 12314390
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1848942433095597, 1582009882530495, 1849292741020143,
-+                1068498323302788, 2001402229799484
-+#else
-+                15683501, 27551389, 18109119, 23573784, 15337967, 27556609,
-+                50391428, 15921865, 16103996, 29823217
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1528282417624269, 2142492439828191, 2179662545816034,
-+                362568973150328, 1591374675250271
-+#else
-+                43939021, 22773182, 13588191, 31925625, 63310306, 32479502,
-+                47835256, 5402698, 37293151, 23713330
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                160026679434388, 232341189218716, 2149181472355545,
-+                598041771119831, 183859001910173
-+#else
-+                23190676, 2384583, 34394524, 3462153, 37205209, 32025299,
-+                55842007, 8911516, 41903005, 2739712
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2013278155187349, 662660471354454, 793981225706267,
-+                411706605985744, 804490933124791
-+#else
-+                21374101, 30000182, 33584214, 9874410, 15377179, 11831242,
-+                33578960, 6134906, 4931255, 11987849
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2051892037280204, 488391251096321, 2230187337030708,
-+                930221970662692, 679002758255210
-+#else
-+                67101132, 30575573, 50885377, 7277596, 105524, 33232381,
-+                35628324, 13861387, 37032554, 10117929
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1530723630438670, 875873929577927, 341560134269988,
-+                449903119530753, 1055551308214179
-+#else
-+                37607694, 22809559, 40945095, 13051538, 41483300, 5089642,
-+                60783361, 6704078, 12890019, 15728940
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1461835919309432, 1955256480136428, 180866187813063,
-+                1551979252664528, 557743861963950
-+#else
-+                45136504, 21783052, 66157804, 29135591, 14704839, 2695116,
-+                903376, 23126293, 12885166, 8311031
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                359179641731115, 1324915145732949, 902828372691474,
-+                294254275669987, 1887036027752957
-+#else
-+                49592363, 5352193, 10384213, 19742774, 7506450, 13453191,
-+                26423267, 4384730, 1888765, 28119028
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2043271609454323, 2038225437857464, 1317528426475850,
-+                1398989128982787, 2027639881006861
-+#else
-+                41291507, 30447119, 53614264, 30371925, 30896458, 19632703,
-+                34857219, 20846562, 47644429, 30214188
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2072902725256516, 312132452743412, 309930885642209,
-+                996244312618453, 1590501300352303
-+#else
-+                43500868, 30888657, 66582772, 4651135, 5765089, 4618330,
-+                6092245, 14845197, 17151279, 23700316
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1397254305160710, 695734355138021, 2233992044438756,
-+                1776180593969996, 1085588199351115
-+#else
-+                42278406, 20820711, 51942885, 10367249, 37577956, 33289075,
-+                22825804, 26467153, 50242379, 16176524
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                440567051331029, 254894786356681, 493869224930222,
-+                1556322069683366, 1567456540319218
-+#else
-+                43525589, 6564960, 20063689, 3798228, 62368686, 7359224,
-+                2006182, 23191006, 38362610, 23356922
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1950722461391320, 1907845598854797, 1822757481635527,
-+                2121567704750244, 73811931471221
-+#else
-+                56482264, 29068029, 53788301, 28429114, 3432135, 27161203,
-+                23632036, 31613822, 32808309, 1099883
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                387139307395758, 2058036430315676, 1220915649965325,
-+                1794832055328951, 1230009312169328
-+#else
-+                15030958, 5768825, 39657628, 30667132, 60681485, 18193060,
-+                51830967, 26745081, 2051440, 18328567
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1765973779329517, 659344059446977, 19821901606666,
-+                1301928341311214, 1116266004075885
-+#else
-+                63746541, 26315059, 7517889, 9824992, 23555850, 295369, 5148398,
-+                19400244, 44422509, 16633659
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1127572801181483, 1224743760571696, 1276219889847274,
-+                1529738721702581, 1589819666871853
-+#else
-+                4577067, 16802144, 13249840, 18250104, 19958762, 19017158,
-+                18559669, 22794883, 8402477, 23690159
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2181229378964934, 2190885205260020, 1511536077659137,
-+                1246504208580490, 668883326494241
-+#else
-+                38702534, 32502850, 40318708, 32646733, 49896449, 22523642,
-+                9453450, 18574360, 17983009, 9967138
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                437866655573314, 669026411194768, 81896997980338,
-+                523874406393178, 245052060935236
-+#else
-+                41346370, 6524721, 26585488, 9969270, 24709298, 1220360,
-+                65430874, 7806336, 17507396, 3651560
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1975438052228868, 1071801519999806, 594652299224319,
-+                1877697652668809, 1489635366987285
-+#else
-+                56688388, 29436320, 14584638, 15971087, 51340543, 8861009,
-+                26556809, 27979875, 48555541, 22197296
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                958592545673770, 233048016518599, 851568750216589,
-+                567703851596087, 1740300006094761
-+#else
-+                2839082, 14284142, 4029895, 3472686, 14402957, 12689363,
-+                40466743, 8459446, 61503401, 25932490
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2014540178270324, 192672779514432, 213877182641530,
-+                2194819933853411, 1716422829364835
-+#else
-+                62269556, 30018987, 9744960, 2871048, 25113978, 3187018,
-+                41998051, 32705365, 17258083, 25576693
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1540769606609725, 2148289943846077, 1597804156127445,
-+                1230603716683868, 815423458809453
-+#else
-+                18164541, 22959256, 49953981, 32012014, 19237077, 23809137,
-+                23357532, 18337424, 26908269, 12150756
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1738560251245018, 1779576754536888, 1783765347671392,
-+                1880170990446751, 1088225159617541
-+#else
-+                36843994, 25906566, 5112248, 26517760, 65609056, 26580174,
-+                43167, 28016731, 34806789, 16215818
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                659303913929492, 1956447718227573, 1830568515922666,
-+                841069049744408, 1669607124206368
-+#else
-+                60209940, 9824393, 54804085, 29153342, 35711722, 27277596,
-+                32574488, 12532905, 59605792, 24879084
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1143465490433355, 1532194726196059, 1093276745494697,
-+                481041706116088, 2121405433561163
-+#else
-+                39765323, 17038963, 39957339, 22831480, 946345, 16291093,
-+                254968, 7168080, 21676107, 31611404
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1686424298744462, 1451806974487153, 266296068846582,
-+                1834686947542675, 1720762336132256
-+#else
-+                21260942, 25129680, 50276977, 21633609, 43430902, 3968120,
-+                63456915, 27338965, 63552672, 25641356
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                889217026388959, 1043290623284660, 856125087551909,
-+                1669272323124636, 1603340330827879
-+#else
-+                16544735, 13250366, 50304436, 15546241, 62525861, 12757257,
-+                64646556, 24874095, 48201831, 23891632
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1206396181488998, 333158148435054, 1402633492821422,
-+                1120091191722026, 1945474114550509
-+#else
-+                64693606, 17976703, 18312302, 4964443, 51836334, 20900867,
-+                26820650, 16690659, 25459437, 28989823
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                766720088232571, 1512222781191002, 1189719893490790,
-+                2091302129467914, 2141418006894941
-+#else
-+                41964155, 11425019, 28423002, 22533875, 60963942, 17728207,
-+                9142794, 31162830, 60676445, 31909614
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                419663647306612, 1998875112167987, 1426599870253707,
-+                1154928355379510, 486538532138187
-+#else
-+                44004212, 6253475, 16964147, 29785560, 41994891, 21257994,
-+                39651638, 17209773, 6335691, 7249989
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                938160078005954, 1421776319053174, 1941643234741774,
-+                180002183320818, 1414380336750546
-+#else
-+                36775618, 13979674, 7503222, 21186118, 55152142, 28932738,
-+                36836594, 2682241, 25993170, 21075909
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                398001940109652, 1577721237663248, 1012748649830402,
-+                1540516006905144, 1011684812884559
-+#else
-+                4364628, 5930691, 32304656, 23509878, 59054082, 15091130,
-+                22857016, 22955477, 31820367, 15075278
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1653276489969630, 6081825167624, 1921777941170836,
-+                1604139841794531, 861211053640641
-+#else
-+                31879134, 24635739, 17258760, 90626, 59067028, 28636722,
-+                24162787, 23903546, 49138625, 12833044
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                996661541407379, 1455877387952927, 744312806857277,
-+                139213896196746, 1000282908547789
-+#else
-+                19073683, 14851414, 42705695, 21694263, 7625277, 11091125,
-+                47489674, 2074448, 57694925, 14905376
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1450817495603008, 1476865707053229, 1030490562252053,
-+                620966950353376, 1744760161539058
-+#else
-+                24483648, 21618865, 64589997, 22007013, 65555733, 15355505,
-+                41826784, 9253128, 27628530, 25998952
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                559728410002599, 37056661641185, 2038622963352006,
-+                1637244893271723, 1026565352238948
-+#else
-+                17597607, 8340603, 19355617, 552187, 26198470, 30377849,
-+                4593323, 24396850, 52997988, 15297015
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                962165956135846, 1116599660248791, 182090178006815,
-+                1455605467021751, 196053588803284
-+#else
-+                510886, 14337390, 35323607, 16638631, 6328095, 2713355,
-+                46891447, 21690211, 8683220, 2921426
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                796863823080135, 1897365583584155, 420466939481601,
-+                2165972651724672, 932177357788289
-+#else
-+                18606791, 11874196, 27155355, 28272950, 43077121, 6265445,
-+                41930624, 32275507, 4674689, 13890525
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                877047233620632, 1375632631944375, 643773611882121,
-+                660022738847877, 19353932331831
-+#else
-+                13609624, 13069022, 39736503, 20498523, 24360585, 9592974,
-+                14977157, 9835105, 4389687, 288396
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2216943882299338, 394841323190322, 2222656898319671,
-+                558186553950529, 1077236877025190
-+#else
-+                9922506, 33035038, 13613106, 5883594, 48350519, 33120168,
-+                54804801, 8317627, 23388070, 16052080
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                801118384953213, 1914330175515892, 574541023311511,
-+                1471123787903705, 1526158900256288
-+#else
-+                12719997, 11937594, 35138804, 28525742, 26900119, 8561328,
-+                46953177, 21921452, 52354592, 22741539
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                949617889087234, 2207116611267331, 912920039141287,
-+                501158539198789, 62362560771472
-+#else
-+                15961858, 14150409, 26716931, 32888600, 44314535, 13603568,
-+                11829573, 7467844, 38286736, 929274
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1474518386765335, 1760793622169197, 1157399790472736,
-+                1622864308058898, 165428294422792
-+#else
-+                11038231, 21972036, 39798381, 26237869, 56610336, 17246600,
-+                43629330, 24182562, 45715720, 2465073
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1961673048027128, 102619413083113, 1051982726768458,
-+                1603657989805485, 1941613251499678
-+#else
-+                20017144, 29231206, 27915241, 1529148, 12396362, 15675764,
-+                13817261, 23896366, 2463390, 28932292
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1401939116319266, 335306339903072, 72046196085786,
-+                862423201496006, 850518754531384
-+#else
-+                50749986, 20890520, 55043680, 4996453, 65852442, 1073571,
-+                9583558, 12851107, 4003896, 12673717
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1234706593321979, 1083343891215917, 898273974314935,
-+                1640859118399498, 157578398571149
-+#else
-+                65377275, 18398561, 63845933, 16143081, 19294135, 13385325,
-+                14741514, 24450706, 7903885, 2348101
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1143483057726416, 1992614991758919, 674268662140796,
-+                1773370048077526, 674318359920189
-+#else
-+                24536016, 17039225, 12715591, 29692277, 1511292, 10047386,
-+                63266518, 26425272, 38731325, 10048126
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1835401379538542, 173900035308392, 818247630716732,
-+                1762100412152786, 1021506399448291
-+#else
-+                54486638, 27349611, 30718824, 2591312, 56491836, 12192839,
-+                18873298, 26257342, 34811107, 15221631
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1506632088156630, 2127481795522179, 513812919490255,
-+                140643715928370, 442476620300318
-+#else
-+                40630742, 22450567, 11546243, 31701949, 9180879, 7656409,
-+                45764914, 2095754, 29769758, 6593415
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2056683376856736, 219094741662735, 2193541883188309,
-+                1841182310235800, 556477468664293
-+#else
-+                35114656, 30646970, 4176911, 3264766, 12538965, 32686321,
-+                26312344, 27435754, 30958053, 8292160
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1315019427910827, 1049075855992603, 2066573052986543,
-+                266904467185534, 2040482348591520
-+#else
-+                31429803, 19595316, 29173531, 15632448, 12174511, 30794338,
-+                32808830, 3977186, 26143136, 30405556
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                94096246544434, 922482381166992, 24517828745563,
-+                2139430508542503, 2097139044231004
-+#else
-+                22648882, 1402143, 44308880, 13746058, 7936347, 365344,
-+                58440231, 31879998, 63350620, 31249806
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                537697207950515, 1399352016347350, 1563663552106345,
-+                2148749520888918, 549922092988516
-+#else
-+                51616947, 8012312, 64594134, 20851969, 43143017, 23300402,
-+                65496150, 32018862, 50444388, 8194477
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1747985413252434, 680511052635695, 1809559829982725,
-+                594274250930054, 201673170745982
-+#else
-+                27338066, 26047012, 59694639, 10140404, 48082437, 26964542,
-+                27277190, 8855376, 28572286, 3005164
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                323583936109569, 1973572998577657, 1192219029966558,
-+                79354804385273, 1374043025560347
-+#else
-+                26287105, 4821776, 25476601, 29408529, 63344350, 17765447,
-+                49100281, 1182478, 41014043, 20474836
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                213277331329947, 416202017849623, 1950535221091783,
-+                1313441578103244, 2171386783823658
-+#else
-+                59937691, 3178079, 23970071, 6201893, 49913287, 29065239,
-+                45232588, 19571804, 32208682, 32356184
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                189088804229831, 993969372859110, 895870121536987,
-+                1547301535298256, 1477373024911350
-+#else
-+                50451143, 2817642, 56822502, 14811297, 6024667, 13349505,
-+                39793360, 23056589, 39436278, 22014573
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1620578418245010, 541035331188469, 2235785724453865,
-+                2154865809088198, 1974627268751826
-+#else
-+                15941010, 24148500, 45741813, 8062054, 31876073, 33315803,
-+                51830470, 32110002, 15397330, 29424239
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1346805451740245, 1350981335690626, 942744349501813,
-+                2155094562545502, 1012483751693409
-+#else
-+                8934485, 20068965, 43822466, 20131190, 34662773, 14047985,
-+                31170398, 32113411, 39603297, 15087183
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2107080134091762, 1132567062788208, 1824935377687210,
-+                769194804343737, 1857941799971888
-+#else
-+                48751602, 31397940, 24524912, 16876564, 15520426, 27193656,
-+                51606457, 11461895, 16788528, 27685490
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1074666112436467, 249279386739593, 1174337926625354,
-+                1559013532006480, 1472287775519121
-+#else
-+                65161459, 16013772, 21750665, 3714552, 49707082, 17498998,
-+                63338576, 23231111, 31322513, 21938797
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1872620123779532, 1892932666768992, 1921559078394978,
-+                1270573311796160, 1438913646755037
-+#else
-+                21426636, 27904214, 53460576, 28206894, 38296674, 28633461,
-+                48833472, 18933017, 13040861, 21441484
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                837390187648199, 1012253300223599, 989780015893987,
-+                1351393287739814, 328627746545550
-+#else
-+                11293895, 12478086, 39972463, 15083749, 37801443, 14748871,
-+                14555558, 20137329, 1613710, 4896935
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1028328827183114, 1711043289969857, 1350832470374933,
-+                1923164689604327, 1495656368846911
-+#else
-+                41213962, 15323293, 58619073, 25496531, 25967125, 20128972,
-+                2825959, 28657387, 43137087, 22287016
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1900828492104143, 430212361082163, 687437570852799,
-+                832514536673512, 1685641495940794
-+#else
-+                51184079, 28324551, 49665331, 6410663, 3622847, 10243618,
-+                20615400, 12405433, 43355834, 25118015
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                842632847936398, 605670026766216, 290836444839585,
-+                163210774892356, 2213815011799645
-+#else
-+                60017550, 12556207, 46917512, 9025186, 50036385, 4333800,
-+                4378436, 2432030, 23097949, 32988414
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1176336383453996, 1725477294339771, 12700622672454,
-+                678015708818208, 162724078519879
-+#else
-+                4565804, 17528778, 20084411, 25711615, 1724998, 189254,
-+                24767264, 10103221, 48596551, 2424777
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1448049969043497, 1789411762943521, 385587766217753,
-+                90201620913498, 832999441066823
-+#else
-+                366633, 21577626, 8173089, 26664313, 30788633, 5745705,
-+                59940186, 1344108, 63466311, 12412658
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                516086333293313, 2240508292484616, 1351669528166508,
-+                1223255565316488, 750235824427138
-+#else
-+                43107073, 7690285, 14929416, 33386175, 34898028, 20141445,
-+                24162696, 18227928, 63967362, 11179384
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1263624896582495, 1102602401673328, 526302183714372,
-+                2152015839128799, 1483839308490010
-+#else
-+                18289503, 18829478, 8056944, 16430056, 45379140, 7842513,
-+                61107423, 32067534, 48424218, 22110928
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                442991718646863, 1599275157036458, 1925389027579192,
-+                899514691371390, 350263251085160
-+#else
-+                476239, 6601091, 60956074, 23831056, 17503544, 28690532,
-+                27672958, 13403813, 11052904, 5219329
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1689713572022143, 593854559254373, 978095044791970,
-+                1985127338729499, 1676069120347625
-+#else
-+                20678527, 25178694, 34436965, 8849122, 62099106, 14574751,
-+                31186971, 29580702, 9014761, 24975376
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1557207018622683, 340631692799603, 1477725909476187,
-+                614735951619419, 2033237123746766
-+#else
-+                53464795, 23204192, 51146355, 5075807, 65594203, 22019831,
-+                34006363, 9160279, 8473550, 30297594
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                968764929340557, 1225534776710944, 662967304013036,
-+                1155521416178595, 791142883466590
-+#else
-+                24900749, 14435722, 17209120, 18261891, 44516588, 9878982,
-+                59419555, 17218610, 42540382, 11788947
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1487081286167458, 993039441814934, 1792378982844640,
-+                698652444999874, 2153908693179754
-+#else
-+                63990690, 22159237, 53306774, 14797440, 9652448, 26708528,
-+                47071426, 10410732, 42540394, 32095740
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1123181311102823, 685575944875442, 507605465509927,
-+                1412590462117473, 568017325228626
-+#else
-+                51449703, 16736705, 44641714, 10215877, 58011687, 7563910,
-+                11871841, 21049238, 48595538, 8464117
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                560258797465417, 2193971151466401, 1824086900849026,
-+                579056363542056, 1690063960036441
-+#else
-+                43708233, 8348506, 52522913, 32692717, 63158658, 27181012,
-+                14325288, 8628612, 33313881, 25183915
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1918407319222416, 353767553059963, 1930426334528099,
-+                1564816146005724, 1861342381708096
-+#else
-+                46921872, 28586496, 22367355, 5271547, 66011747, 28765593,
-+                42303196, 23317577, 58168128, 27736162
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2131325168777276, 1176636658428908, 1756922641512981,
-+                1390243617176012, 1966325177038383
-+#else
-+                60160060, 31759219, 34483180, 17533252, 32635413, 26180187,
-+                15989196, 20716244, 28358191, 29300528
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2063958120364491, 2140267332393533, 699896251574968,
-+                273268351312140, 375580724713232
-+#else
-+                43547083, 30755372, 34757181, 31892468, 57961144, 10429266,
-+                50471180, 4072015, 61757200, 5596588
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2024297515263178, 416959329722687, 1079014235017302,
-+                171612225573183, 1031677520051053
-+#else
-+                38872266, 30164383, 12312895, 6213178, 3117142, 16078565,
-+                29266239, 2557221, 1768301, 15373193
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2033900009388450, 1744902869870788, 2190580087917640,
-+                1949474984254121, 231049754293748
-+#else
-+                59865506, 30307471, 62515396, 26001078, 66980936, 32642186,
-+                66017961, 29049440, 42448372, 3442909
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                343868674606581, 550155864008088, 1450580864229630,
-+                481603765195050, 896972360018042
-+#else
-+                36898293, 5124042, 14181784, 8197961, 18964734, 21615339,
-+                22597930, 7176455, 48523386, 13365929
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2151139328380127, 314745882084928, 59756825775204,
-+                1676664391494651, 2048348075599360
-+#else
-+                59231455, 32054473, 8324672, 4690079, 6261860, 890446, 24538107,
-+                24984246, 57419264, 30522764
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1528930066340597, 1605003907059576, 1055061081337675,
-+                1458319101947665, 1234195845213142
-+#else
-+                25008885, 22782833, 62803832, 23916421, 16265035, 15721635,
-+                683793, 21730648, 15723478, 18390951
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                830430507734812, 1780282976102377, 1425386760709037,
-+                362399353095425, 2168861579799910
-+#else
-+                57448220, 12374378, 40101865, 26528283, 59384749, 21239917,
-+                11879681, 5400171, 519526, 32318556
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1155762232730333, 980662895504006, 2053766700883521,
-+                490966214077606, 510405877041357
-+#else
-+                22258397, 17222199, 59239046, 14613015, 44588609, 30603508,
-+                46754982, 7315966, 16648397, 7605640
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1683750316716132, 652278688286128, 1221798761193539,
-+                1897360681476669, 319658166027343
-+#else
-+                59027556, 25089834, 58885552, 9719709, 19259459, 18206220,
-+                23994941, 28272877, 57640015, 4763277
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                618808732869972, 72755186759744, 2060379135624181,
-+                1730731526741822, 48862757828238
-+#else
-+                45409620, 9220968, 51378240, 1084136, 41632757, 30702041,
-+                31088446, 25789909, 55752334, 728111
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1463171970593505, 1143040711767452, 614590986558883,
-+                1409210575145591, 1882816996436803
-+#else
-+                26047201, 21802961, 60208540, 17032633, 24092067, 9158119,
-+                62835319, 20998873, 37743427, 28056159
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2230133264691131, 563950955091024, 2042915975426398,
-+                827314356293472, 672028980152815
-+#else
-+                17510331, 33231575, 5854288, 8403524, 17133918, 30441820,
-+                38997856, 12327944, 10750447, 10014012
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                264204366029760, 1654686424479449, 2185050199932931,
-+                2207056159091748, 506015669043634
-+#else
-+                56796096, 3936951, 9156313, 24656749, 16498691, 32559785,
-+                39627812, 32887699, 3424690, 7540221
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1784446333136569, 1973746527984364, 334856327359575,
-+                1156769775884610, 1023950124675478
-+#else
-+                30322361, 26590322, 11361004, 29411115, 7433303, 4989748,
-+                60037442, 17237212, 57864598, 15258045
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2065270940578383, 31477096270353, 306421879113491,
-+                181958643936686, 1907105536686083
-+#else
-+                13054543, 30774935, 19155473, 469045, 54626067, 4566041,
-+                5631406, 2711395, 1062915, 28418087
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1496516440779464, 1748485652986458, 872778352227340,
-+                818358834654919, 97932669284220
-+#else
-+                47868616, 22299832, 37599834, 26054466, 61273100, 13005410,
-+                61042375, 12194496, 32960380, 1459310
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                471636015770351, 672455402793577, 1804995246884103,
-+                1842309243470804, 1501862504981682
-+#else
-+                19852015, 7027924, 23669353, 10020366, 8586503, 26896525,
-+                394196, 27452547, 18638002, 22379495
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1013216974933691, 538921919682598, 1915776722521558,
-+                1742822441583877, 1886550687916656
-+#else
-+                31395515, 15098109, 26581030, 8030562, 50580950, 28547297,
-+                9012485, 25970078, 60465776, 28111795
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2094270000643336, 303971879192276, 40801275554748,
-+                649448917027930, 1818544418535447
-+#else
-+                57916680, 31207054, 65111764, 4529533, 25766844, 607986,
-+                67095642, 9677542, 34813975, 27098423
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2241737709499165, 549397817447461, 838180519319392,
-+                1725686958520781, 1705639080897747
-+#else
-+                64664349, 33404494, 29348901, 8186665, 1873760, 12489863,
-+                36174285, 25714739, 59256019, 25416002
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1216074541925116, 50120933933509, 1565829004133810,
-+                721728156134580, 349206064666188
-+#else
-+                51872508, 18120922, 7766469, 746860, 26346930, 23332670,
-+                39775412, 10754587, 57677388, 5203575
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                948617110470858, 346222547451945, 1126511960599975,
-+                1759386906004538, 493053284802266
-+#else
-+                31834314, 14135496, 66338857, 5159117, 20917671, 16786336,
-+                59640890, 26216907, 31809242, 7347066
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1454933046815146, 874696014266362, 1467170975468588,
-+                1432316382418897, 2111710746366763
-+#else
-+                57502122, 21680191, 20414458, 13033986, 13716524, 21862551,
-+                19797969, 21343177, 15192875, 31466942
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2105387117364450, 1996463405126433, 1303008614294500,
-+                851908115948209, 1353742049788635
-+#else
-+                54445282, 31372712, 1168161, 29749623, 26747876, 19416341,
-+                10609329, 12694420, 33473243, 20172328
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                750300956351719, 1487736556065813, 15158817002104,
-+                1511998221598392, 971739901354129
-+#else
-+                33184999, 11180355, 15832085, 22169002, 65475192, 225883,
-+                15089336, 22530529, 60973201, 14480052
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1874648163531693, 2124487685930551, 1810030029384882,
-+                918400043048335, 586348627300650
-+#else
-+                31308717, 27934434, 31030839, 31657333, 15674546, 26971549,
-+                5496207, 13685227, 27595050, 8737275
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1235084464747900, 1166111146432082, 1745394857881591,
-+                1405516473883040, 4463504151617
-+#else
-+                46790012, 18404192, 10933842, 17376410, 8335351, 26008410,
-+                36100512, 20943827, 26498113, 66511
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1663810156463827, 327797390285791, 1341846161759410,
-+                1964121122800605, 1747470312055380
-+#else
-+                22644435, 24792703, 50437087, 4884561, 64003250, 19995065,
-+                30540765, 29267685, 53781076, 26039336
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                660005247548233, 2071860029952887, 1358748199950107,
-+                911703252219107, 1014379923023831
-+#else
-+                39091017, 9834844, 18617207, 30873120, 63706907, 20246925,
-+                8205539, 13585437, 49981399, 15115438
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2206641276178231, 1690587809721504, 1600173622825126,
-+                2156096097634421, 1106822408548216
-+#else
-+                23711543, 32881517, 31206560, 25191721, 6164646, 23844445,
-+                33572981, 32128335, 8236920, 16492939
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1344788193552206, 1949552134239140, 1735915881729557,
-+                675891104100469, 1834220014427292
-+#else
-+                43198286, 20038905, 40809380, 29050590, 25005589, 25867162,
-+                19574901, 10071562, 6708380, 27332008
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1920949492387964, 158885288387530, 70308263664033,
-+                626038464897817, 1468081726101009
-+#else
-+                2101372, 28624378, 19702730, 2367575, 51681697, 1047674,
-+                5301017, 9328700, 29955601, 21876122
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                622221042073383, 1210146474039168, 1742246422343683,
-+                1403839361379025, 417189490895736
-+#else
-+                3096359, 9271816, 45488000, 18032587, 52260867, 25961494,
-+                41216721, 20918836, 57191288, 6216607
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                22727256592983, 168471543384997, 1324340989803650,
-+                1839310709638189, 504999476432775
-+#else
-+                34493015, 338662, 41913253, 2510421, 37895298, 19734218,
-+                24822829, 27407865, 40341383, 7525078
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1313240518756327, 1721896294296942, 52263574587266,
-+                2065069734239232, 804910473424630
-+#else
-+                44042215, 19568808, 16133486, 25658254, 63719298, 778787,
-+                66198528, 30771936, 47722230, 11994100
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1337466662091884, 1287645354669772, 2018019646776184,
-+                652181229374245, 898011753211715
-+#else
-+                21691500, 19929806, 66467532, 19187410, 3285880, 30070836,
-+                42044197, 9718257, 59631427, 13381417
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1969792547910734, 779969968247557, 2011350094423418,
-+                1823964252907487, 1058949448296945
-+#else
-+                18445390, 29352196, 14979845, 11622458, 65381754, 29971451,
-+                23111647, 27179185, 28535281, 15779576
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                207343737062002, 1118176942430253, 758894594548164,
-+                806764629546266, 1157700123092949
-+#else
-+                30098034, 3089662, 57874477, 16662134, 45801924, 11308410,
-+                53040410, 12021729, 9955285, 17251076
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1273565321399022, 1638509681964574, 759235866488935,
-+                666015124346707, 897983460943405
-+#else
-+                9734894, 18977602, 59635230, 24415696, 2060391, 11313496,
-+                48682835, 9924398, 20194861, 13380996
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1717263794012298, 1059601762860786, 1837819172257618,
-+                1054130665797229, 680893204263559
-+#else
-+                40730762, 25589224, 44941042, 15789296, 49053522, 27385639,
-+                65123949, 15707770, 26342023, 10146099
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2237039662793603, 2249022333361206, 2058613546633703,
-+                149454094845279, 2215176649164582
-+#else
-+                41091971, 33334488, 21339190, 33513044, 19745255, 30675732,
-+                37471583, 2227039, 21612326, 33008704
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                79472182719605, 1851130257050174, 1825744808933107,
-+                821667333481068, 781795293511946
-+#else
-+                54031477, 1184227, 23562814, 27583990, 46757619, 27205717,
-+                25764460, 12243797, 46252298, 11649657
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                755822026485370, 152464789723500, 1178207602290608,
-+                410307889503239, 156581253571278
-+#else
-+                57077370, 11262625, 27384172, 2271902, 26947504, 17556661,
-+                39943, 6114064, 33514190, 2333242
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1418185496130297, 484520167728613, 1646737281442950,
-+                1401487684670265, 1349185550126961
-+#else
-+                45675257, 21132610, 8119781, 7219913, 45278342, 24538297,
-+                60429113, 20883793, 24350577, 20104431
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1495380034400429, 325049476417173, 46346894893933,
-+                1553408840354856, 828980101835683
-+#else
-+                62992557, 22282898, 43222677, 4843614, 37020525, 690622,
-+                35572776, 23147595, 8317859, 12352766
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1280337889310282, 2070832742866672, 1640940617225222,
-+                2098284908289951, 450929509534434
-+#else
-+                18200138, 19078521, 34021104, 30857812, 43406342, 24451920,
-+                43556767, 31266881, 20712162, 6719373
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                407703353998781, 126572141483652, 286039827513621,
-+                1999255076709338, 2030511179441770
-+#else
-+                26656189, 6075253, 59250308, 1886071, 38764821, 4262325,
-+                11117530, 29791222, 26224234, 30256974
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1254958221100483, 1153235960999843, 942907704968834,
-+                637105404087392, 1149293270147267
-+#else
-+                49939907, 18700334, 63713187, 17184554, 47154818, 14050419,
-+                21728352, 9493610, 18620611, 17125804
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                894249020470196, 400291701616810, 406878712230981,
-+                1599128793487393, 1145868722604026
-+#else
-+                53785524, 13325348, 11432106, 5964811, 18609221, 6062965,
-+                61839393, 23828875, 36407290, 17074774
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1497955250203334, 110116344653260, 1128535642171976,
-+                1900106496009660, 129792717460909
-+#else
-+                43248326, 22321272, 26961356, 1640861, 34695752, 16816491,
-+                12248508, 28313793, 13735341, 1934062
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                452487513298665, 1352120549024569, 1173495883910956,
-+                1999111705922009, 367328130454226
-+#else
-+                25089769, 6742589, 17081145, 20148166, 21909292, 17486451,
-+                51972569, 29789085, 45830866, 5473615
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1717539401269642, 1475188995688487, 891921989653942,
-+                836824441505699, 1885988485608364
-+#else
-+                31883658, 25593331, 1083431, 21982029, 22828470, 13290673,
-+                59983779, 12469655, 29111212, 28103418
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1241784121422547, 187337051947583, 1118481812236193,
-+                428747751936362, 30358898927325
-+#else
-+                24244947, 18504025, 40845887, 2791539, 52111265, 16666677,
-+                24367466, 6388839, 56813277, 452382
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2022432361201842, 1088816090685051, 1977843398539868,
-+                1854834215890724, 564238862029357
-+#else
-+                41468082, 30136590, 5217915, 16224624, 19987036, 29472163,
-+                42872612, 27639183, 15766061, 8407814
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                938868489100585, 1100285072929025, 1017806255688848,
-+                1957262154788833, 152787950560442
-+#else
-+                46701865, 13990230, 15495425, 16395525, 5377168, 15166495,
-+                58191841, 29165478, 59040954, 2276717
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                867319417678923, 620471962942542, 226032203305716,
-+                342001443957629, 1761675818237336
-+#else
-+                30157899, 12924066, 49396814, 9245752, 19895028, 3368142,
-+                43281277, 5096218, 22740376, 26251015
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1295072362439987, 931227904689414, 1355731432641687,
-+                922235735834035, 892227229410209
-+#else
-+                2041139, 19298082, 7783686, 13876377, 41161879, 20201972,
-+                24051123, 13742383, 51471265, 13295221
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1680989767906154, 535362787031440, 2136691276706570,
-+                1942228485381244, 1267350086882274
-+#else
-+                33338218, 25048699, 12532112, 7977527, 9106186, 31839181,
-+                49388668, 28941459, 62657506, 18884987
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                366018233770527, 432660629755596, 126409707644535,
-+                1973842949591662, 645627343442376
-+#else
-+                47063583, 5454096, 52762316, 6447145, 28862071, 1883651,
-+                64639598, 29412551, 7770568, 9620597
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                535509430575217, 546885533737322, 1524675609547799,
-+                2138095752851703, 1260738089896827
-+#else
-+                23208049, 7979712, 33071466, 8149229, 1758231, 22719437,
-+                30945527, 31860109, 33606523, 18786461
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1159906385590467, 2198530004321610, 714559485023225,
-+                81880727882151, 1484020820037082
-+#else
-+                1439939, 17283952, 66028874, 32760649, 4625401, 10647766,
-+                62065063, 1220117, 30494170, 22113633
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1377485731340769, 2046328105512000, 1802058637158797,
-+                62146136768173, 1356993908853901
-+#else
-+                62071265, 20526136, 64138304, 30492664, 15640973, 26852766,
-+                40369837, 926049, 65424525, 20220784
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2013612215646735, 1830770575920375, 536135310219832,
-+                609272325580394, 270684344495013
-+#else
-+                13908495, 30005160, 30919927, 27280607, 45587000, 7989038,
-+                9021034, 9078865, 3353509, 4033511
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1237542585982777, 2228682050256790, 1385281931622824,
-+                593183794882890, 493654978552689
-+#else
-+                37445433, 18440821, 32259990, 33209950, 24295848, 20642309,
-+                23161162, 8839127, 27485041, 7356032
-+#endif
-+            }},
-+        },
-+    },
-+    {
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                47341488007760, 1891414891220257, 983894663308928,
-+                176161768286818, 1126261115179708
-+#else
-+                9661008, 705443, 11980065, 28184278, 65480320, 14661172,
-+                60762722, 2625014, 28431036, 16782598
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1694030170963455, 502038567066200, 1691160065225467,
-+                949628319562187, 275110186693066
-+#else
-+                43269631, 25243016, 41163352, 7480957, 49427195, 25200248,
-+                44562891, 14150564, 15970762, 4099461
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1124515748676336, 1661673816593408, 1499640319059718,
-+                1584929449166988, 558148594103306
-+#else
-+                29262576, 16756590, 26350592, 24760869, 8529670, 22346382,
-+                13617292, 23617289, 11465738, 8317062
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1784525599998356, 1619698033617383, 2097300287550715,
-+                258265458103756, 1905684794832758
-+#else
-+                41615764, 26591503, 32500199, 24135381, 44070139, 31252209,
-+                14898636, 3848455, 20969334, 28396916
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1288941072872766, 931787902039402, 190731008859042,
-+                2006859954667190, 1005931482221702
-+#else
-+                46724414, 19206718, 48772458, 13884721, 34069410, 2842113,
-+                45498038, 29904543, 11177094, 14989547
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1465551264822703, 152905080555927, 680334307368453,
-+                173227184634745, 666407097159852
-+#else
-+                42612143, 21838415, 16959895, 2278463, 12066309, 10137771,
-+                13515641, 2581286, 38621356, 9930239
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2111017076203943, 1378760485794347, 1248583954016456,
-+                1352289194864422, 1895180776543896
-+#else
-+                49357223, 31456605, 16544299, 20545132, 51194056, 18605350,
-+                18345766, 20150679, 16291480, 28240394
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                171348223915638, 662766099800389, 462338943760497,
-+                466917763340314, 656911292869115
-+#else
-+                33879670, 2553287, 32678213, 9875984, 8534129, 6889387,
-+                57432090, 6957616, 4368891, 9788741
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                488623681976577, 866497561541722, 1708105560937768,
-+                1673781214218839, 1506146329818807
-+#else
-+                16660737, 7281060, 56278106, 12911819, 20108584, 25452756,
-+                45386327, 24941283, 16250551, 22443329
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                160425464456957, 950394373239689, 430497123340934,
-+                711676555398832, 320964687779005
-+#else
-+                47343357, 2390525, 50557833, 14161979, 1905286, 6414907,
-+                4689584, 10604807, 36918461, 4782746
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                988979367990485, 1359729327576302, 1301834257246029,
-+                294141160829308, 29348272277475
-+#else
-+                65754325, 14736940, 59741422, 20261545, 7710541, 19398842,
-+                57127292, 4383044, 22546403, 437323
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1434382743317910, 100082049942065, 221102347892623,
-+                186982837860588, 1305765053501834
-+#else
-+                31665558, 21373968, 50922033, 1491338, 48740239, 3294681,
-+                27343084, 2786261, 36475274, 19457415
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                2205916462268190, 499863829790820, 961960554686616,
-+                158062762756985, 1841471168298305
-+#else
-+                52641566, 32870716, 33734756, 7448551, 19294360, 14334329,
-+                47418233, 2355318, 47824193, 27440058
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1191737341426592, 1847042034978363, 1382213545049056,
-+                1039952395710448, 788812858896859
-+#else
-+                15121312, 17758270, 6377019, 27523071, 56310752, 20596586,
-+                18952176, 15496498, 37728731, 11754227
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1346965964571152, 1291881610839830, 2142916164336056,
-+                786821641205979, 1571709146321039
-+#else
-+                64471568, 20071356, 8488726, 19250536, 12728760, 31931939,
-+                7141595, 11724556, 22761615, 23420291
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                787164375951248, 202869205373189, 1356590421032140,
-+                1431233331032510, 786341368775957
-+#else
-+                16918416, 11729663, 49025285, 3022986, 36093132, 20214772,
-+                38367678, 21327038, 32851221, 11717399
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                492448143532951, 304105152670757, 1761767168301056,
-+                233782684697790, 1981295323106089
-+#else
-+                11166615, 7338049, 60386341, 4531519, 37640192, 26252376,
-+                31474878, 3483633, 65915689, 29523600
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                665807507761866, 1343384868355425, 895831046139653,
-+                439338948736892, 1986828765695105
-+#else
-+                66923210, 9921304, 31456609, 20017994, 55095045, 13348922,
-+                33142652, 6546660, 47123585, 29606055
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                756096210874553, 1721699973539149, 258765301727885,
-+                1390588532210645, 1212530909934781
-+#else
-+                34648249, 11266711, 55911757, 25655328, 31703693, 3855903,
-+                58571733, 20721383, 36336829, 18068118
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                852891097972275, 1816988871354562, 1543772755726524,
-+                1174710635522444, 202129090724628
-+#else
-+                49102387, 12709067, 3991746, 27075244, 45617340, 23004006,
-+                35973516, 17504552, 10928916, 3011958
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1205281565824323, 22430498399418, 992947814485516,
-+                1392458699738672, 688441466734558
-+#else
-+                60151107, 17960094, 31696058, 334240, 29576716, 14796075,
-+                36277808, 20749251, 18008030, 10258577
-+#endif
-+            }},
-+        },
-+        {
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1050627428414972, 1955849529137135, 2171162376368357,
-+                91745868298214, 447733118757826
-+#else
-+                44660220, 15655568, 7018479, 29144429, 36794597, 32352840,
-+                65255398, 1367119, 25127874, 6671743
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1287181461435438, 622722465530711, 880952150571872,
-+                741035693459198, 311565274989772
-+#else
-+                29701166, 19180498, 56230743, 9279287, 67091296, 13127209,
-+                21382910, 11042292, 25838796, 4642684
-+#endif
-+            }},
-+            {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+                1003649078149734, 545233927396469, 1849786171789880,
-+                1318943684880434, 280345687170552
-+#else
-+                46678630, 14955536, 42982517, 8124618, 61739576, 27563961,
-+                30468146, 19653792, 18423288, 4177476
-+#endif
-+            }},
-+        },
-+    },
-+};
-+
-+#endif  // CONFIG_SMALL
-+
-+// Bi[i] = (2*i+1)*B
-+static const ge_precomp Bi[8] = {
-+    {
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            1288382639258501, 245678601348599, 269427782077623,
-+            1462984067271730, 137412439391563
-+#else
-+            25967493, 19198397, 29566455, 3660896, 54414519, 4014786, 27544626,
-+            21800161, 61029707, 2047604
-+#endif
-+        }},
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            62697248952638, 204681361388450, 631292143396476, 338455783676468,
-+            1213667448819585
-+#else
-+            54563134, 934261, 64385954, 3049989, 66381436, 9406985, 12720692,
-+            5043384, 19500929, 18085054
-+#endif
-+        }},
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            301289933810280, 1259582250014073, 1422107436869536,
-+            796239922652654, 1953934009299142
-+#else
-+            58370664, 4489569, 9688441, 18769238, 10184608, 21191052, 29287918,
-+            11864899, 42594502, 29115885
-+#endif
-+        }},
-+    },
-+    {
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            1601611775252272, 1720807796594148, 1132070835939856,
-+            1260455018889551, 2147779492816911
-+#else
-+            15636272, 23865875, 24204772, 25642034, 616976, 16869170, 27787599,
-+            18782243, 28944399, 32004408
-+#endif
-+        }},
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            316559037616741, 2177824224946892, 1459442586438991,
-+            1461528397712656, 751590696113597
-+#else
-+            16568933, 4717097, 55552716, 32452109, 15682895, 21747389, 16354576,
-+            21778470, 7689661, 11199574
-+#endif
-+        }},
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            1850748884277385, 1200145853858453, 1068094770532492,
-+            672251375690438, 1586055907191707
-+#else
-+            30464137, 27578307, 55329429, 17883566, 23220364, 15915852, 7512774,
-+            10017326, 49359771, 23634074
-+#endif
-+        }},
-+    },
-+    {
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            769950342298419, 132954430919746, 844085933195555, 974092374476333,
-+            726076285546016
-+#else
-+            10861363, 11473154, 27284546, 1981175, 37044515, 12577860, 32867885,
-+            14515107, 51670560, 10819379
-+#endif
-+        }},
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            425251763115706, 608463272472562, 442562545713235, 837766094556764,
-+            374555092627893
-+#else
-+            4708026, 6336745, 20377586, 9066809, 55836755, 6594695, 41455196,
-+            12483687, 54440373, 5581305
-+#endif
-+        }},
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            1086255230780037, 274979815921559, 1960002765731872,
-+            929474102396301, 1190409889297339
-+#else
-+            19563141, 16186464, 37722007, 4097518, 10237984, 29206317, 28542349,
-+            13850243, 43430843, 17738489
-+#endif
-+        }},
-+    },
-+    {
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            665000864555967, 2065379846933859, 370231110385876, 350988370788628,
-+            1233371373142985
-+#else
-+            5153727, 9909285, 1723747, 30776558, 30523604, 5516873, 19480852,
-+            5230134, 43156425, 18378665
-+#endif
-+        }},
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            2019367628972465, 676711900706637, 110710997811333,
-+            1108646842542025, 517791959672113
-+#else
-+            36839857, 30090922, 7665485, 10083793, 28475525, 1649722, 20654025,
-+            16520125, 30598449, 7715701
-+#endif
-+        }},
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            965130719900578, 247011430587952, 526356006571389, 91986625355052,
-+            2157223321444601
-+#else
-+            28881826, 14381568, 9657904, 3680757, 46927229, 7843315, 35708204,
-+            1370707, 29794553, 32145132
-+#endif
-+        }},
-+    },
-+    {
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            1802695059465007, 1664899123557221, 593559490740857,
-+            2160434469266659, 927570450755031
-+#else
-+            44589871, 26862249, 14201701, 24808930, 43598457, 8844725, 18474211,
-+            32192982, 54046167, 13821876
-+#endif
-+        }},
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            1725674970513508, 1933645953859181, 1542344539275782,
-+            1767788773573747, 1297447965928905
-+#else
-+            60653668, 25714560, 3374701, 28813570, 40010246, 22982724, 31655027,
-+            26342105, 18853321, 19333481
-+#endif
-+        }},
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            1381809363726107, 1430341051343062, 2061843536018959,
-+            1551778050872521, 2036394857967624
-+#else
-+            4566811, 20590564, 38133974, 21313742, 59506191, 30723862, 58594505,
-+            23123294, 2207752, 30344648
-+#endif
-+        }},
-+    },
-+    {
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            1970894096313054, 528066325833207, 1619374932191227,
-+            2207306624415883, 1169170329061080
-+#else
-+            41954014, 29368610, 29681143, 7868801, 60254203, 24130566, 54671499,
-+            32891431, 35997400, 17421995
-+#endif
-+        }},
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            2070390218572616, 1458919061857835, 624171843017421,
-+            1055332792707765, 433987520732508
-+#else
-+            25576264, 30851218, 7349803, 21739588, 16472781, 9300885, 3844789,
-+            15725684, 171356, 6466918
-+#endif
-+        }},
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            893653801273833, 1168026499324677, 1242553501121234,
-+            1306366254304474, 1086752658510815
-+#else
-+            23103977, 13316479, 9739013, 17404951, 817874, 18515490, 8965338,
-+            19466374, 36393951, 16193876
-+#endif
-+        }},
-+    },
-+    {
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            213454002618221, 939771523987438, 1159882208056014, 317388369627517,
-+            621213314200687
-+#else
-+            33587053, 3180712, 64714734, 14003686, 50205390, 17283591, 17238397,
-+            4729455, 49034351, 9256799
-+#endif
-+        }},
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            1971678598905747, 338026507889165, 762398079972271, 655096486107477,
-+            42299032696322
-+#else
-+            41926547, 29380300, 32336397, 5036987, 45872047, 11360616, 22616405,
-+            9761698, 47281666, 630304
-+#endif
-+        }},
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            177130678690680, 1754759263300204, 1864311296286618,
-+            1180675631479880, 1292726903152791
-+#else
-+            53388152, 2639452, 42871404, 26147950, 9494426, 27780403, 60554312,
-+            17593437, 64659607, 19263131
-+#endif
-+        }},
-+    },
-+    {
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            1913163449625248, 460779200291993, 2193883288642314,
-+            1008900146920800, 1721983679009502
-+#else
-+            63957664, 28508356, 9282713, 6866145, 35201802, 32691408, 48168288,
-+            15033783, 25105118, 25659556
-+#endif
-+        }},
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            1070401523076875, 1272492007800961, 1910153608563310,
-+            2075579521696771, 1191169788841221
-+#else
-+            42782475, 15950225, 35307649, 18961608, 55446126, 28463506, 1573891,
-+            30928545, 2198789, 17749813
-+#endif
-+        }},
-+        {{
-+#if defined(BORINGSSL_CURVE25519_64BIT)
-+            692896803108118, 500174642072499, 2068223309439677,
-+            1162190621851337, 1426986007309901
-+#else
-+            64009494, 10324966, 64867251, 7453182, 61661885, 30818928, 53296841,
-+            17317989, 34647629, 21263748
-+#endif
-+        }},
-+    },
-+};
-diff --git a/src/plugins/preauth/spake/groups.c b/src/plugins/preauth/spake/groups.c
-new file mode 100644
-index 000000000..a195cc195
---- /dev/null
-+++ b/src/plugins/preauth/spake/groups.c
-@@ -0,0 +1,442 @@
-+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-+/* plugins/preauth/spake/groups.c - SPAKE group interfaces */
-+/*
-+ * Copyright (C) 2015 by the Massachusetts Institute of Technology.
-+ * 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.
-+ *
-+ * 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 HOLDER 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.
-+ */
-+
-+/*
-+ * The SPAKE2 algorithm works as follows:
-+ *
-+ * 1. The parties agree on a group, a base element G, and constant elements M
-+ *    and N.  In this mechanism, these parameters are determined by the
-+ *    registered group number.
-+ * 2. Both parties derive a scalar value w from the initial key.
-+ * 3. The first party (the KDC, in this mechanism) chooses a random secret
-+ *    scalar x and sends T=xG+wM.
-+ * 4. The second party (the client, in this mechanism) chooses a random
-+ *    secret scalar y and sends S=yG+wN.
-+ * 5. The first party computes K=x(S-wN).
-+ * 6. The second party computes the same value as K=y(T-wM).
-+ * 7. Both parties derive a key from a random oracle whose input incorporates
-+ *    the party identities, w, T, S, and K.
-+ *
-+ * We implement the algorithm using a vtable for each group, where the primary
-+ * vtable methods are "keygen" (corresponding to step 3 or 4) and "result"
-+ * (corresponding to step 5 or 6).  We use the term "private scalar" to refer
-+ * to x or y, and "public element" to refer to S or T.
-+ */
-+
-+#include "iana.h"
-+#include "trace.h"
-+#include "groups.h"
-+
-+#define DEFAULT_GROUPS_CLIENT "edwards25519"
-+#define DEFAULT_GROUPS_KDC ""
-+
-+typedef struct groupent_st {
-+    const groupdef *gdef;
-+    groupdata *gdata;
-+} groupent;
-+
-+struct groupstate_st {
-+    krb5_boolean is_kdc;
-+
-+    /* Permitted and groups, from configuration */
-+    int32_t *permitted;
-+    size_t npermitted;
-+
-+    /* Optimistic challenge group, from configuration */
-+    int32_t challenge_group;
-+
-+    /* Lazily-initialized list of gdata objects. */
-+    groupent *data;
-+    size_t ndata;
-+};
-+
-+extern groupdef builtin_edwards25519;
-+#ifdef SPAKE_OPENSSL
-+extern groupdef ossl_P256;
-+extern groupdef ossl_P384;
-+extern groupdef ossl_P521;
-+#endif
-+
-+static const groupdef *groupdefs[] = {
-+    &builtin_edwards25519,
-+#ifdef SPAKE_OPENSSL
-+    &ossl_P256,
-+    &ossl_P384,
-+    &ossl_P521,
-+#endif
-+    NULL
-+};
-+
-+/* Find a groupdef structure by group number.  Return NULL on failure. */
-+static const groupdef *
-+find_gdef(int32_t group)
-+{
-+    size_t i;
-+
-+    for (i = 0; groupdefs[i] != NULL; i++) {
-+        if (groupdefs[i]->reg->id == group)
-+            return groupdefs[i];
-+    }
-+
-+    return NULL;
-+}
-+
-+/* Find a group number by name.  Return 0 on failure. */
-+static int32_t
-+find_gnum(const char *name)
-+{
-+    size_t i;
-+
-+    for (i = 0; groupdefs[i] != NULL; i++) {
-+        if (strcasecmp(name, groupdefs[i]->reg->name) == 0)
-+            return groupdefs[i]->reg->id;
-+    }
-+    return 0;
-+}
-+
-+static krb5_boolean
-+in_grouplist(const int32_t *list, size_t count, int32_t group)
-+{
-+    size_t i;
-+
-+    for (i = 0; i < count; i++) {
-+        if (list[i] == group)
-+            return TRUE;
-+    }
-+
-+    return FALSE;
-+}
-+
-+/* Retrieve a group data object for group within gstate, lazily initializing it
-+ * if necessary. */
-+static krb5_error_code
-+get_gdata(krb5_context context, groupstate *gstate, const groupdef *gdef,
-+          groupdata **gdata_out)
-+{
-+    krb5_error_code ret;
-+    groupent *ent, *newptr;
-+
-+    *gdata_out = NULL;
-+
-+    /* Look for an existing entry. */
-+    for (ent = gstate->data; ent < gstate->data + gstate->ndata; ent++) {
-+        if (ent->gdef == gdef) {
-+            *gdata_out = ent->gdata;
-+            return 0;
-+        }
-+    }
-+
-+    /* Make a new entry. */
-+    newptr = realloc(gstate->data, (gstate->ndata + 1) * sizeof(groupent));
-+    if (newptr == NULL)
-+        return ENOMEM;
-+    gstate->data = newptr;
-+    ent = &gstate->data[gstate->ndata];
-+    ent->gdef = gdef;
-+    ent->gdata = NULL;
-+    if (gdef->init != NULL) {
-+        ret = gdef->init(context, gdef, &ent->gdata);
-+        if (ret)
-+            return ret;
-+    }
-+    gstate->ndata++;
-+    *gdata_out = ent->gdata;
-+    return 0;
-+}
-+
-+/* Destructively parse str into a list of group numbers. */
-+static krb5_error_code
-+parse_groups(krb5_context context, char *str, int32_t **list_out,
-+             size_t *count_out)
-+{
-+    const char *const delim = " \t\r\n,";
-+    char *token, *save = NULL;
-+    int32_t group, *newptr, *list = NULL;
-+    size_t count = 0;
-+
-+    *list_out = NULL;
-+    *count_out = 0;
-+
-+    /* Walk through the words in profstr. */
-+    for (token = strtok_r(str, delim, &save); token != NULL;
-+         token = strtok_r(NULL, delim, &save)) {
-+        group = find_gnum(token);
-+        if (!group) {
-+            TRACE_SPAKE_UNKNOWN_GROUP(context, token);
-+            continue;
-+        }
-+        if (in_grouplist(list, count, group))
-+            continue;
-+        newptr = realloc(list, (count + 1) * sizeof(*list));
-+        if (newptr == NULL) {
-+            free(list);
-+            return ENOMEM;
-+        }
-+        list = newptr;
-+        list[count++] = group;
-+    }
-+
-+    *list_out = list;
-+    *count_out = count;
-+    return 0;
-+}
-+
-+krb5_error_code
-+group_init_state(krb5_context context, krb5_boolean is_kdc,
-+                 groupstate **gstate_out)
-+{
-+    krb5_error_code ret;
-+    groupstate *gstate;
-+    const char *defgroups;
-+    char *profstr1 = NULL, *profstr2 = NULL;
-+    int32_t *permitted = NULL, challenge_group = 0;
-+    size_t npermitted;
-+
-+    *gstate_out = NULL;
-+
-+    defgroups = is_kdc ? DEFAULT_GROUPS_KDC : DEFAULT_GROUPS_CLIENT;
-+    ret = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS,
-+                             KRB5_CONF_SPAKE_PREAUTH_GROUPS, NULL, defgroups,
-+                             &profstr1);
-+    if (ret)
-+        goto cleanup;
-+    ret = parse_groups(context, profstr1, &permitted, &npermitted);
-+    if (ret)
-+        goto cleanup;
-+    if (npermitted == 0) {
-+        ret = KRB5_PLUGIN_OP_NOTSUPP;
-+        k5_setmsg(context, ret, _("No SPAKE preauth groups configured"));
-+        goto cleanup;
-+    }
-+
-+    if (is_kdc) {
-+        /*
-+         * Check for a configured optimistic challenge group.  If one is set,
-+         * the KDC will send a challenge in the PREAUTH_REQUIRED method data,
-+         * before receiving the list of supported groups.
-+         */
-+        ret = profile_get_string(context->profile, KRB5_CONF_KDCDEFAULTS,
-+                                 KRB5_CONF_SPAKE_PREAUTH_KDC_CHALLENGE, NULL,
-+                                 NULL, &profstr2);
-+        if (ret)
-+            goto cleanup;
-+        if (profstr2 != NULL) {
-+            challenge_group = find_gnum(profstr2);
-+            if (!in_grouplist(permitted, npermitted, challenge_group)) {
-+                ret = KRB5_PLUGIN_OP_NOTSUPP;
-+                k5_setmsg(context, ret,
-+                          _("SPAKE challenge group not a permitted group: %s"),
-+                          profstr2);
-+                goto cleanup;
-+            }
-+        }
-+    }
-+
-+    gstate = k5alloc(sizeof(*gstate), &ret);
-+    if (gstate == NULL)
-+        goto cleanup;
-+    gstate->is_kdc = is_kdc;
-+    gstate->permitted = permitted;
-+    gstate->npermitted = npermitted;
-+    gstate->challenge_group = challenge_group;
-+    permitted = NULL;
-+    gstate->data = NULL;
-+    gstate->ndata = 0;
-+    *gstate_out = gstate;
-+
-+cleanup:
-+    profile_release_string(profstr1);
-+    profile_release_string(profstr2);
-+    free(permitted);
-+    return ret;
-+}
-+
-+
-+void
-+group_free_state(groupstate *gstate)
-+{
-+    groupent *ent;
-+
-+    for (ent = gstate->data; ent < gstate->data + gstate->ndata; ent++) {
-+        if (ent->gdata != NULL && ent->gdef->fini != NULL)
-+            ent->gdef->fini(ent->gdata);
-+    }
-+
-+    free(gstate->permitted);
-+    free(gstate->data);
-+    free(gstate);
-+}
-+
-+krb5_boolean
-+group_is_permitted(groupstate *gstate, int32_t group)
-+{
-+    return in_grouplist(gstate->permitted, gstate->npermitted, group);
-+}
-+
-+void
-+group_get_permitted(groupstate *gstate, int32_t **list_out, int32_t *count_out)
-+{
-+    *list_out = gstate->permitted;
-+    *count_out = gstate->npermitted;
-+}
-+
-+krb5_int32
-+group_optimistic_challenge(groupstate *gstate)
-+{
-+    assert(gstate->is_kdc);
-+    return gstate->challenge_group;
-+}
-+
-+krb5_error_code
-+group_mult_len(int32_t group, size_t *len_out)
-+{
-+    const groupdef *gdef;
-+
-+    *len_out = 0;
-+    gdef = find_gdef(group);
-+    if (gdef == NULL)
-+        return EINVAL;
-+    *len_out = gdef->reg->mult_len;
-+    return 0;
-+}
-+
-+krb5_error_code
-+group_keygen(krb5_context context, groupstate *gstate, int32_t group,
-+             const krb5_data *wbytes, krb5_data *priv_out, krb5_data *pub_out)
-+{
-+    krb5_error_code ret;
-+    const groupdef *gdef;
-+    groupdata *gdata;
-+    uint8_t *priv = NULL, *pub = NULL;
-+
-+    *priv_out = empty_data();
-+    *pub_out = empty_data();
-+    gdef = find_gdef(group);
-+    if (gdef == NULL || wbytes->length != gdef->reg->mult_len)
-+        return EINVAL;
-+    ret = get_gdata(context, gstate, gdef, &gdata);
-+    if (ret)
-+        return ret;
-+
-+    priv = k5alloc(gdef->reg->mult_len, &ret);
-+    if (priv == NULL)
-+        goto cleanup;
-+    pub = k5alloc(gdef->reg->elem_len, &ret);
-+    if (pub == NULL)
-+        goto cleanup;
-+
-+    ret = gdef->keygen(context, gdata, (uint8_t *)wbytes->data, gstate->is_kdc,
-+                       priv, pub);
-+    if (ret)
-+        goto cleanup;
-+
-+    *priv_out = make_data(priv, gdef->reg->mult_len);
-+    *pub_out = make_data(pub, gdef->reg->elem_len);
-+    priv = pub = NULL;
-+    TRACE_SPAKE_KEYGEN(context, pub_out);
-+
-+cleanup:
-+    zapfree(priv, gdef->reg->mult_len);
-+    free(pub);
-+    return ret;
-+}
-+
-+krb5_error_code
-+group_result(krb5_context context, groupstate *gstate, int32_t group,
-+             const krb5_data *wbytes, const krb5_data *ourpriv,
-+             const krb5_data *theirpub, krb5_data *spakeresult_out)
-+{
-+    krb5_error_code ret;
-+    const groupdef *gdef;
-+    groupdata *gdata;
-+    uint8_t *spakeresult = NULL;
-+
-+    *spakeresult_out = empty_data();
-+    gdef = find_gdef(group);
-+    if (gdef == NULL || wbytes->length != gdef->reg->mult_len)
-+        return EINVAL;
-+    if (ourpriv->length != gdef->reg->mult_len ||
-+        theirpub->length != gdef->reg->elem_len)
-+        return EINVAL;
-+    ret = get_gdata(context, gstate, gdef, &gdata);
-+    if (ret)
-+        return ret;
-+
-+    spakeresult = k5alloc(gdef->reg->elem_len, &ret);
-+    if (spakeresult == NULL)
-+        goto cleanup;
-+
-+    /* Invert is_kdc here to use the other party's constant. */
-+    ret = gdef->result(context, gdata, (uint8_t *)wbytes->data,
-+                       (uint8_t *)ourpriv->data, (uint8_t *)theirpub->data,
-+                       !gstate->is_kdc, spakeresult);
-+    if (ret)
-+        goto cleanup;
-+
-+    *spakeresult_out = make_data(spakeresult, gdef->reg->elem_len);
-+    spakeresult = NULL;
-+    TRACE_SPAKE_RESULT(context, spakeresult_out);
-+
-+cleanup:
-+    zapfree(spakeresult, gdef->reg->elem_len);
-+    return ret;
-+}
-+
-+krb5_error_code
-+group_hash_len(int32_t group, size_t *len_out)
-+{
-+    const groupdef *gdef;
-+
-+    *len_out = 0;
-+    gdef = find_gdef(group);
-+    if (gdef == NULL)
-+        return EINVAL;
-+    *len_out = gdef->reg->hash_len;
-+    return 0;
-+}
-+
-+krb5_error_code
-+group_hash(krb5_context context, groupstate *gstate, int32_t group,
-+           const krb5_data *dlist, size_t ndata, uint8_t *result_out)
-+{
-+    krb5_error_code ret;
-+    const groupdef *gdef;
-+    groupdata *gdata;
-+
-+    gdef = find_gdef(group);
-+    if (gdef == NULL)
-+        return EINVAL;
-+    ret = get_gdata(context, gstate, gdef, &gdata);
-+    if (ret)
-+        return ret;
-+    return gdef->hash(context, gdata, dlist, ndata, result_out);
-+}
-diff --git a/src/plugins/preauth/spake/groups.h b/src/plugins/preauth/spake/groups.h
-new file mode 100644
-index 000000000..3add69494
---- /dev/null
-+++ b/src/plugins/preauth/spake/groups.h
-@@ -0,0 +1,148 @@
-+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-+/* plugins/preauth/spake/groups.h - SPAKE group interfaces */
-+/*
-+ * Copyright (C) 2015 by the Massachusetts Institute of Technology.
-+ * 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.
-+ *
-+ * 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 HOLDER 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.
-+ */
-+
-+#ifndef GROUPS_H
-+#define GROUPS_H
-+
-+#include "k5-int.h"
-+#include "iana.h"
-+
-+typedef struct groupstate_st groupstate;
-+typedef struct groupdata_st groupdata;
-+typedef struct groupdef_st groupdef;
-+
-+struct groupdef_st {
-+    const spake_iana *reg;
-+
-+    /*
-+     * Optional: create a per-group data object to allow more efficient keygen
-+     * and result computations.  Saving a reference to gdef is okay; its
-+     * lifetime will always be longer than the resulting object.
-+     */
-+    krb5_error_code (*init)(krb5_context context, const groupdef *gdef,
-+                            groupdata **gdata_out);
-+
-+    /* Optional: release a group data object. */
-+    void (*fini)(groupdata *gdata);
-+
-+    /*
-+     * Mandatory: generate a random private scalar (x or y) and a public
-+     * element (T or S), using wbytes for the w value.  If use_m is true, use
-+     * the M element (generating T); otherwise use the N element (generating
-+     * S).  wbytes and priv_out have length reg->mult_len; pub_out has length
-+     * reg->elem_len.  priv_out and pub_out are caller-allocated.
-+     */
-+    krb5_error_code (*keygen)(krb5_context context, groupdata *gdata,
-+                              const uint8_t *wbytes, krb5_boolean use_m,
-+                              uint8_t *priv_out, uint8_t *pub_out);
-+
-+    /*
-+     * Mandatory: compute K given a private scalar (x or y) and the other
-+     * party's public element (S or T), using wbytes for the w value.  If use_m
-+     * is true, use the M element (computing K from y and T); otherwise use the
-+     * N element (computing K from x and S).  wbytes and ourpriv have length
-+     * reg->mult_len; theirpub and elem_out have length reg->elem_len.
-+     * elem_out is caller-allocated.
-+     */
-+    krb5_error_code (*result)(krb5_context context, groupdata *gdata,
-+                              const uint8_t *wbytes, const uint8_t *ourpriv,
-+                              const uint8_t *theirpub, krb5_boolean use_m,
-+                              uint8_t *elem_out);
-+
-+    /*
-+     * Mandatory: compute the group's specified hash function over datas (with
-+     * ndata elements), placing the result in result_out.  result_out is
-+     * caller-allocated with length reg->hash_len.
-+     */
-+    krb5_error_code (*hash)(krb5_context context, groupdata *gdata,
-+                            const krb5_data *datas, size_t ndata,
-+                            uint8_t *result_out);
-+};
-+
-+/* Initialize an object which holds group configuration and pre-computation
-+ * state for each group.  is_kdc is true for KDCs, false for clients. */
-+krb5_error_code group_init_state(krb5_context context, krb5_boolean is_kdc,
-+                                 groupstate **out);
-+
-+/* Release resources held by gstate. */
-+void group_free_state(groupstate *gstate);
-+
-+/* Return true if group is permitted by configuration. */
-+krb5_boolean group_is_permitted(groupstate *gstate, int32_t group);
-+
-+/* Set *list_out and *count_out to the list of groups permitted by
-+ * configuration. */
-+void group_get_permitted(groupstate *gstate, int32_t **list_out,
-+                         int32_t *count_out);
-+
-+/* Return the KDC optimistic challenge group if one is configured.  Valid for
-+ * KDC groupstate objects only. */
-+krb5_int32 group_optimistic_challenge(groupstate *gstate);
-+
-+/* Set *len_out to the multiplier length for group. */
-+krb5_error_code group_mult_len(int32_t group, size_t *len_out);
-+
-+/*
-+ * Generate a SPAKE private scalar (x or y) and public element (T or S), given
-+ * an input multiplier wbytes.  Use constant M if gstate is a KDC groupstate
-+ * object, N if it is a client object.  Allocate storage and place the results
-+ * in *priv_out and *pub_out.
-+ */
-+krb5_error_code group_keygen(krb5_context context, groupstate *gstate,
-+                             int32_t group, const krb5_data *wbytes,
-+                             krb5_data *priv_out, krb5_data *pub_out);
-+
-+/*
-+ * Compute the SPAKE result K from our private scalar (x or y) and their public
-+ * key (S or T), deriving the input scalar w from ikey.  Use the other party's
-+ * constant, N if gstate is a KDC groupstate object or M if it is a client
-+ * object.  Allocate storage and place the result in *spakeresult_out.
-+ */
-+krb5_error_code group_result(krb5_context context, groupstate *gstate,
-+                             int32_t group, const krb5_data *wbytes,
-+                             const krb5_data *ourpriv,
-+                             const krb5_data *theirpub,
-+                             krb5_data *spakeresult_out);
-+
-+/* Set *result_out to the hash output length for group. */
-+krb5_error_code group_hash_len(int32_t group, size_t *result_out);
-+
-+/*
-+ * Compute the group's specified hash function over dlist (with ndata
-+ * elements).  result_out is caller-allocated with enough bytes for the hash
-+ * output as given by group_hash_len().
-+ */
-+krb5_error_code group_hash(krb5_context context, groupstate *gstate,
-+                           int32_t group, const krb5_data *dlist, size_t ndata,
-+                           uint8_t *result_out);
-+
-+#endif /* GROUPS_H */
-diff --git a/src/plugins/preauth/spake/iana.c b/src/plugins/preauth/spake/iana.c
-new file mode 100644
-index 000000000..e7901dedf
---- /dev/null
-+++ b/src/plugins/preauth/spake/iana.c
-@@ -0,0 +1,108 @@
-+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-+/* plugins/preauth/spake/iana.c - SPAKE IANA registry contents */
-+/*
-+ * Copyright (C) 2015 by the Massachusetts Institute of Technology.
-+ * 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.
-+ *
-+ * 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 HOLDER 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 "iana.h"
-+
-+static uint8_t edwards25519_M[] = {
-+    0xD0, 0x48, 0x03, 0x2C, 0x6E, 0xA0, 0xB6, 0xD6, 0x97, 0xDD, 0xC2, 0xE8,
-+    0x6B, 0xDA, 0x85, 0xA3, 0x3A, 0xDA, 0xC9, 0x20, 0xF1, 0xBF, 0x18, 0xE1,
-+    0xB0, 0xC6, 0xD1, 0x66, 0xA5, 0xCE, 0xCD, 0xAF
-+};
-+
-+static uint8_t edwards25519_N[] = {
-+    0xD3, 0xBF, 0xB5, 0x18, 0xF4, 0x4F, 0x34, 0x30, 0xF2, 0x9D, 0x0C, 0x92,
-+    0xAF, 0x50, 0x38, 0x65, 0xA1, 0xED, 0x32, 0x81, 0xDC, 0x69, 0xB3, 0x5D,
-+    0xD8, 0x68, 0xBA, 0x85, 0xF8, 0x86, 0xC4, 0xAB
-+};
-+
-+static uint8_t P256_M[] = {
-+    0x02, 0x88, 0x6E, 0x2F, 0x97, 0xAC, 0xE4, 0x6E, 0x55, 0xBA, 0x9D, 0xD7,
-+    0x24, 0x25, 0x79, 0xF2, 0x99, 0x3B, 0x64, 0xE1, 0x6E, 0xF3, 0xDC, 0xAB,
-+    0x95, 0xAF, 0xD4, 0x97, 0x33, 0x3D, 0x8F, 0xA1, 0x2F
-+};
-+
-+static uint8_t P256_N[] = {
-+    0x03, 0xD8, 0xBB, 0xD6, 0xC6, 0x39, 0xC6, 0x29, 0x37, 0xB0, 0x4D, 0x99,
-+    0x7F, 0x38, 0xC3, 0x77, 0x07, 0x19, 0xC6, 0x29, 0xD7, 0x01, 0x4D, 0x49,
-+    0xA2, 0x4B, 0x4F, 0x98, 0xBA, 0xA1, 0x29, 0x2B, 0x49
-+};
-+
-+static uint8_t P384_M[] = {
-+    0x03, 0x0F, 0xF0, 0x89, 0x5A, 0xE5, 0xEB, 0xF6, 0x18, 0x70, 0x80, 0xA8,
-+    0x2D, 0x82, 0xB4, 0x2E, 0x27, 0x65, 0xE3, 0xB2, 0xF8, 0x74, 0x9C, 0x7E,
-+    0x05, 0xEB, 0xA3, 0x66, 0x43, 0x4B, 0x36, 0x3D, 0x3D, 0xC3, 0x6F, 0x15,
-+    0x31, 0x47, 0x39, 0x07, 0x4D, 0x2E, 0xB8, 0x61, 0x3F, 0xCE, 0xEC, 0x28,
-+    0x53
-+};
-+
-+static uint8_t P384_N[] = {
-+    0x02, 0xC7, 0x2C, 0xF2, 0xE3, 0x90, 0x85, 0x3A, 0x1C, 0x1C, 0x4A, 0xD8,
-+    0x16, 0xA6, 0x2F, 0xD1, 0x58, 0x24, 0xF5, 0x60, 0x78, 0x91, 0x8F, 0x43,
-+    0xF9, 0x22, 0xCA, 0x21, 0x51, 0x8F, 0x9C, 0x54, 0x3B, 0xB2, 0x52, 0xC5,
-+    0x49, 0x02, 0x14, 0xCF, 0x9A, 0xA3, 0xF0, 0xBA, 0xAB, 0x4B, 0x66, 0x5C,
-+    0x10
-+};
-+
-+static uint8_t P521_M[] = {
-+    0x02, 0x00, 0x3F, 0x06, 0xF3, 0x81, 0x31, 0xB2, 0xBA, 0x26, 0x00, 0x79,
-+    0x1E, 0x82, 0x48, 0x8E, 0x8D, 0x20, 0xAB, 0x88, 0x9A, 0xF7, 0x53, 0xA4,
-+    0x18, 0x06, 0xC5, 0xDB, 0x18, 0xD3, 0x7D, 0x85, 0x60, 0x8C, 0xFA, 0xE0,
-+    0x6B, 0x82, 0xE4, 0xA7, 0x2C, 0xD7, 0x44, 0xC7, 0x19, 0x19, 0x35, 0x62,
-+    0xA6, 0x53, 0xEA, 0x1F, 0x11, 0x9E, 0xEF, 0x93, 0x56, 0x90, 0x7E, 0xDC,
-+    0x9B, 0x56, 0x97, 0x99, 0x62, 0xD7, 0xAA
-+};
-+
-+static uint8_t P521_N[] = {
-+    0x02, 0x00, 0xC7, 0x92, 0x4B, 0x9E, 0xC0, 0x17, 0xF3, 0x09, 0x45, 0x62,
-+    0x89, 0x43, 0x36, 0xA5, 0x3C, 0x50, 0x16, 0x7B, 0xA8, 0xC5, 0x96, 0x38,
-+    0x76, 0x88, 0x05, 0x42, 0xBC, 0x66, 0x9E, 0x49, 0x4B, 0x25, 0x32, 0xD7,
-+    0x6C, 0x5B, 0x53, 0xDF, 0xB3, 0x49, 0xFD, 0xF6, 0x91, 0x54, 0xB9, 0xE0,
-+    0x04, 0x8C, 0x58, 0xA4, 0x2E, 0x8E, 0xD0, 0x4C, 0xEF, 0x05, 0x2A, 0x3B,
-+    0xC3, 0x49, 0xD9, 0x55, 0x75, 0xCD, 0x25
-+};
-+
-+const spake_iana spake_iana_edwards25519 = {
-+    SPAKE_GROUP_EDWARDS25519, "edwards25519", 32, 32,
-+    edwards25519_M, edwards25519_N, 32
-+};
-+
-+const spake_iana spake_iana_p256 = {
-+    SPAKE_GROUP_P256, "P-256", 32, 33, P256_M, P256_N, 32
-+};
-+
-+const spake_iana spake_iana_p384 = {
-+    SPAKE_GROUP_P384, "P-384", 48, 49, P384_M, P384_N, 48
-+};
-+
-+const spake_iana spake_iana_p521 = {
-+    SPAKE_GROUP_P521, "P-521", 66, 67, P521_M, P521_N, 64
-+};
-diff --git a/src/plugins/preauth/spake/iana.h b/src/plugins/preauth/spake/iana.h
-new file mode 100644
-index 000000000..1d99c4dd6
---- /dev/null
-+++ b/src/plugins/preauth/spake/iana.h
-@@ -0,0 +1,65 @@
-+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-+/* plugins/preauth/spake/iana.h - SPAKE IANA registry contents */
-+/*
-+ * Copyright (C) 2015 by the Massachusetts Institute of Technology.
-+ * 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.
-+ *
-+ * 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 HOLDER 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.
-+ */
-+
-+#ifndef IANA_H
-+#define IANA_H
-+
-+#include <stdint.h>
-+#include <stddef.h>
-+
-+typedef enum {
-+    SPAKE_SF_NONE = 1,
-+} spake_sf_type;
-+
-+typedef enum {
-+    SPAKE_GROUP_EDWARDS25519 = 1,
-+    SPAKE_GROUP_P256 = 2,
-+    SPAKE_GROUP_P384 = 3,
-+    SPAKE_GROUP_P521 = 4,
-+} spake_group;
-+
-+typedef struct {
-+    int32_t id;
-+    const char *name;
-+    size_t mult_len;
-+    size_t elem_len;
-+    const uint8_t *m;
-+    const uint8_t *n;
-+    size_t hash_len;
-+} spake_iana;
-+
-+extern const spake_iana spake_iana_edwards25519;
-+extern const spake_iana spake_iana_p256;
-+extern const spake_iana spake_iana_p384;
-+extern const spake_iana spake_iana_p521;
-+
-+#endif /* IANA_H */
-diff --git a/src/plugins/preauth/spake/openssl.c b/src/plugins/preauth/spake/openssl.c
-new file mode 100644
-index 000000000..b821a9158
---- /dev/null
-+++ b/src/plugins/preauth/spake/openssl.c
-@@ -0,0 +1,315 @@
-+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-+/* plugins/preauth/spake/openssl.c - SPAKE implementations using OpenSSL */
-+/*
-+ * Copyright (C) 2015 by the Massachusetts Institute of Technology.
-+ * 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.
-+ *
-+ * 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 HOLDER 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 "k5-int.h"
-+
-+#include "groups.h"
-+#include "iana.h"
-+
-+#ifdef SPAKE_OPENSSL
-+#include <openssl/bn.h>
-+#include <openssl/ec.h>
-+#include <openssl/obj_mac.h>
-+#include <openssl/evp.h>
-+
-+/* OpenSSL 1.1 standardizes constructor and destructor names, renaming
-+ * EVP_MD_CTX_create and EVP_MD_CTX_destroy. */
-+#if OPENSSL_VERSION_NUMBER < 0x10100000L
-+#define EVP_MD_CTX_new EVP_MD_CTX_create
-+#define EVP_MD_CTX_free EVP_MD_CTX_destroy
-+#endif
-+
-+struct groupdata_st {
-+    const groupdef *gdef;
-+    EC_GROUP *group;
-+    BIGNUM *order;
-+    BN_CTX *ctx;
-+    EC_POINT *M;
-+    EC_POINT *N;
-+    const EVP_MD *md;
-+};
-+
-+static void
-+ossl_fini(groupdata *gd)
-+{
-+    if (gd == NULL)
-+        return;
-+
-+    EC_GROUP_free(gd->group);
-+    EC_POINT_free(gd->M);
-+    EC_POINT_free(gd->N);
-+    BN_CTX_free(gd->ctx);
-+    BN_free(gd->order);
-+}
-+
-+static krb5_error_code
-+ossl_init(krb5_context context, const groupdef *gdef, groupdata **gdata_out)
-+{
-+    const spake_iana *reg = gdef->reg;
-+    const EVP_MD *md;
-+    groupdata *gd;
-+    int nid;
-+
-+    switch (reg->id) {
-+    case SPAKE_GROUP_P256:
-+        nid = NID_X9_62_prime256v1;
-+        md = EVP_sha256();
-+        break;
-+    case SPAKE_GROUP_P384:
-+        nid = NID_secp384r1;
-+        md = EVP_sha384();
-+        break;
-+    case SPAKE_GROUP_P521:
-+        nid = NID_secp521r1;
-+        md = EVP_sha512();
-+        break;
-+    default:
-+        return EINVAL;
-+    };
-+
-+    gd = calloc(1, sizeof(*gd));
-+    if (gd == NULL)
-+        return ENOMEM;
-+    gd->gdef = gdef;
-+
-+    gd->group = EC_GROUP_new_by_curve_name(nid);
-+    if (gd->group == NULL)
-+        goto error;
-+
-+    gd->ctx = BN_CTX_new();
-+    if (gd->ctx == NULL)
-+        goto error;
-+
-+    gd->order = BN_new();
-+    if (gd->order == NULL)
-+        goto error;
-+    if (!EC_GROUP_get_order(gd->group, gd->order, gd->ctx))
-+        goto error;
-+
-+    gd->M = EC_POINT_new(gd->group);
-+    if (gd->M == NULL)
-+        goto error;
-+    if (!EC_POINT_oct2point(gd->group, gd->M, reg->m, reg->elem_len, gd->ctx))
-+        goto error;
-+
-+    gd->N = EC_POINT_new(gd->group);
-+    if (gd->N == NULL)
-+        goto error;
-+    if (!EC_POINT_oct2point(gd->group, gd->N, reg->n, reg->elem_len, gd->ctx))
-+        goto error;
-+
-+    gd->md = md;
-+
-+    *gdata_out = gd;
-+    return 0;
-+
-+error:
-+    ossl_fini(gd);
-+    return ENOMEM;
-+}
-+
-+/* Convert pseudo-random bytes into a scalar value in constant time.
-+ * Return NULL on failure. */
-+static BIGNUM *
-+unmarshal_w(const groupdata *gdata, const uint8_t *wbytes)
-+{
-+    const spake_iana *reg = gdata->gdef->reg;
-+    BIGNUM *w = NULL;
-+
-+    w = BN_new();
-+    if (w == NULL)
-+        return NULL;
-+
-+    BN_set_flags(w, BN_FLG_CONSTTIME);
-+
-+    if (BN_bin2bn(wbytes, reg->mult_len, w) &&
-+        BN_div(NULL, w, w, gdata->order, gdata->ctx))
-+        return w;
-+
-+    BN_free(w);
-+    return NULL;
-+}
-+
-+static krb5_error_code
-+ossl_keygen(krb5_context context, groupdata *gdata, const uint8_t *wbytes,
-+            krb5_boolean use_m, uint8_t *priv_out, uint8_t *pub_out)
-+{
-+    const spake_iana *reg = gdata->gdef->reg;
-+    const EC_POINT *constant = use_m ? gdata->M : gdata->N;
-+    krb5_boolean success = FALSE;
-+    EC_POINT *pub = NULL;
-+    BIGNUM *priv = NULL, *w = NULL;
-+    size_t len;
-+
-+    w = unmarshal_w(gdata, wbytes);
-+    if (w == NULL)
-+        goto cleanup;
-+
-+    pub = EC_POINT_new(gdata->group);
-+    if (pub == NULL)
-+        goto cleanup;
-+
-+    priv = BN_new();
-+    if (priv == NULL)
-+        goto cleanup;
-+
-+    if (!BN_rand_range(priv, gdata->order))
-+        goto cleanup;
-+
-+    /* Compute priv*G + w*constant; EC_POINT_mul() does this in one call. */
-+    if (!EC_POINT_mul(gdata->group, pub, priv, constant, w, gdata->ctx))
-+        goto cleanup;
-+
-+    /* Marshal priv into priv_out. */
-+    memset(priv_out, 0, reg->mult_len);
-+    BN_bn2bin(priv, &priv_out[reg->mult_len - BN_num_bytes(priv)]);
-+
-+    /* Marshal pub into pub_out. */
-+    len = EC_POINT_point2oct(gdata->group, pub, POINT_CONVERSION_COMPRESSED,
-+                             pub_out, reg->elem_len, gdata->ctx);
-+    if (len != reg->elem_len)
-+        goto cleanup;
-+
-+    success = TRUE;
-+
-+cleanup:
-+    EC_POINT_free(pub);
-+    BN_clear_free(priv);
-+    BN_clear_free(w);
-+    return success ? 0 : ENOMEM;
-+}
-+
-+static krb5_error_code
-+ossl_result(krb5_context context, groupdata *gdata, const uint8_t *wbytes,
-+            const uint8_t *ourpriv, const uint8_t *theirpub,
-+            krb5_boolean use_m, uint8_t *elem_out)
-+{
-+    const spake_iana *reg = gdata->gdef->reg;
-+    const EC_POINT *constant = use_m ? gdata->M : gdata->N;
-+    krb5_boolean success = FALSE, invalid = FALSE;
-+    EC_POINT *result = NULL, *pub = NULL;
-+    BIGNUM *priv = NULL, *w = NULL;
-+    size_t len;
-+
-+    w = unmarshal_w(gdata, wbytes);
-+    if (w == NULL)
-+        goto cleanup;
-+
-+    priv = BN_bin2bn(ourpriv, reg->mult_len, NULL);
-+    if (priv == NULL)
-+        goto cleanup;
-+
-+    pub = EC_POINT_new(gdata->group);
-+    if (pub == NULL)
-+        goto cleanup;
-+    if (!EC_POINT_oct2point(gdata->group, pub, theirpub, reg->elem_len,
-+                            gdata->ctx)) {
-+        invalid = TRUE;
-+        goto cleanup;
-+    }
-+
-+    /* Compute result = priv*(pub - w*constant), using result to hold the
-+     * intermediate steps. */
-+    result = EC_POINT_new(gdata->group);
-+    if (result == NULL)
-+        goto cleanup;
-+    if (!EC_POINT_mul(gdata->group, result, NULL, constant, w, gdata->ctx))
-+        goto cleanup;
-+    if (!EC_POINT_invert(gdata->group, result, gdata->ctx))
-+        goto cleanup;
-+    if (!EC_POINT_add(gdata->group, result, pub, result, gdata->ctx))
-+        goto cleanup;
-+    if (!EC_POINT_mul(gdata->group, result, NULL, result, priv, gdata->ctx))
-+        goto cleanup;
-+
-+    /* Marshal result into elem_out. */
-+    len = EC_POINT_point2oct(gdata->group, result, POINT_CONVERSION_COMPRESSED,
-+                             elem_out, reg->elem_len, gdata->ctx);
-+    if (len != reg->elem_len)
-+        goto cleanup;
-+
-+    success = TRUE;
-+
-+cleanup:
-+    BN_clear_free(priv);
-+    BN_clear_free(w);
-+    EC_POINT_free(pub);
-+    EC_POINT_clear_free(result);
-+    return invalid ? EINVAL : (success ? 0 : ENOMEM);
-+}
-+
-+static krb5_error_code
-+ossl_hash(krb5_context context, groupdata *gdata, const krb5_data *dlist,
-+          size_t ndata, uint8_t *result_out)
-+{
-+    EVP_MD_CTX *ctx;
-+    size_t i;
-+    int ok;
-+
-+    ctx = EVP_MD_CTX_new();
-+    if (ctx == NULL)
-+        return ENOMEM;
-+    ok = EVP_DigestInit_ex(ctx, gdata->md, NULL);
-+    for (i = 0; i < ndata; i++)
-+        ok = ok && EVP_DigestUpdate(ctx, dlist[i].data, dlist[i].length);
-+    ok = ok && EVP_DigestFinal_ex(ctx, result_out, NULL);
-+    EVP_MD_CTX_free(ctx);
-+    return ok ? 0 : ENOMEM;
-+}
-+
-+groupdef ossl_P256 = {
-+    .reg = &spake_iana_p256,
-+    .init = ossl_init,
-+    .fini = ossl_fini,
-+    .keygen = ossl_keygen,
-+    .result = ossl_result,
-+    .hash = ossl_hash,
-+};
-+
-+groupdef ossl_P384 = {
-+    .reg = &spake_iana_p384,
-+    .init = ossl_init,
-+    .fini = ossl_fini,
-+    .keygen = ossl_keygen,
-+    .result = ossl_result,
-+    .hash = ossl_hash,
-+};
-+
-+groupdef ossl_P521 = {
-+    .reg = &spake_iana_p521,
-+    .init = ossl_init,
-+    .fini = ossl_fini,
-+    .keygen = ossl_keygen,
-+    .result = ossl_result,
-+    .hash = ossl_hash,
-+};
-+#endif /* SPAKE_OPENSSL */
-diff --git a/src/plugins/preauth/spake/spake.exports b/src/plugins/preauth/spake/spake.exports
-new file mode 100644
-index 000000000..81d100228
---- /dev/null
-+++ b/src/plugins/preauth/spake/spake.exports
-@@ -0,0 +1,2 @@
-+clpreauth_spake_initvt
-+kdcpreauth_spake_initvt
-diff --git a/src/plugins/preauth/spake/spake_client.c b/src/plugins/preauth/spake/spake_client.c
-new file mode 100644
-index 000000000..d72bd64aa
---- /dev/null
-+++ b/src/plugins/preauth/spake/spake_client.c
-@@ -0,0 +1,363 @@
-+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-+/* plugins/preauth/spake/spake_client.c - SPAKE clpreauth module */
-+/*
-+ * Copyright (C) 2015 by the Massachusetts Institute of Technology.
-+ * 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.
-+ *
-+ * 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 HOLDER 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 "k5-int.h"
-+#include "k5-spake.h"
-+#include "trace.h"
-+#include "util.h"
-+#include "iana.h"
-+#include "groups.h"
-+#include <krb5/clpreauth_plugin.h>
-+
-+typedef struct reqstate_st {
-+    krb5_keyblock *initial_key;
-+    krb5_data *support;
-+    krb5_data thash;
-+    krb5_data spakeresult;
-+} reqstate;
-+
-+static krb5_error_code
-+spake_init(krb5_context context, krb5_clpreauth_moddata *moddata_out)
-+{
-+    krb5_error_code ret;
-+    groupstate *gstate;
-+
-+    ret = group_init_state(context, FALSE, &gstate);
-+    if (ret)
-+        return ret;
-+    *moddata_out = (krb5_clpreauth_moddata)gstate;
-+    return 0;
-+}
-+
-+static void
-+spake_fini(krb5_context context, krb5_clpreauth_moddata moddata)
-+{
-+    group_free_state((groupstate *)moddata);
-+}
-+
-+static void
-+spake_request_init(krb5_context context, krb5_clpreauth_moddata moddata,
-+                   krb5_clpreauth_modreq *modreq_out)
-+{
-+    *modreq_out = calloc(1, sizeof(reqstate));
-+}
-+
-+static void
-+spake_request_fini(krb5_context context, krb5_clpreauth_moddata moddata,
-+                   krb5_clpreauth_modreq modreq)
-+{
-+    reqstate *st = (reqstate *)modreq;
-+
-+    krb5_free_keyblock(context, st->initial_key);
-+    krb5_free_data(context, st->support);
-+    krb5_free_data_contents(context, &st->thash);
-+    zapfree(st->spakeresult.data, st->spakeresult.length);
-+    free(st);
-+}
-+
-+static krb5_error_code
-+spake_prep_questions(krb5_context context, krb5_clpreauth_moddata moddata,
-+                     krb5_clpreauth_modreq modreq,
-+                     krb5_get_init_creds_opt *opt, krb5_clpreauth_callbacks cb,
-+                     krb5_clpreauth_rock rock, krb5_kdc_req *req,
-+                     krb5_data *enc_req, krb5_data *enc_prev_req,
-+                     krb5_pa_data *pa_data)
-+{
-+    reqstate *st = (reqstate *)modreq;
-+
-+    if (st == NULL)
-+        return ENOMEM;
-+    if (st->initial_key == NULL && pa_data->length > 0)
-+        cb->need_as_key(context, rock);
-+
-+    /* When second-factor is implemented, we should ask questions based on the
-+     * factors in the challenge. */
-+
-+    return 0;
-+}
-+
-+/*
-+ * Output a PA-SPAKE support message indicating which groups we support.  This
-+ * may be done for optimistic preauth, in response to an empty message, or in
-+ * response to a challenge using a group we do not support.  Save the support
-+ * message in st->support.
-+ */
-+static krb5_error_code
-+send_support(krb5_context context, groupstate *gstate, reqstate *st,
-+             krb5_pa_data ***pa_out)
-+{
-+    krb5_error_code ret;
-+    krb5_data *support;
-+    krb5_pa_spake msg;
-+
-+    msg.choice = SPAKE_MSGTYPE_SUPPORT;
-+    group_get_permitted(gstate, &msg.u.support.groups, &msg.u.support.ngroups);
-+    ret = encode_krb5_pa_spake(&msg, &support);
-+    if (ret)
-+        return ret;
-+
-+    /* Save the support message for later use in the transcript hash. */
-+    ret = krb5_copy_data(context, support, &st->support);
-+    if (ret) {
-+        krb5_free_data(context, support);
-+        return ret;
-+    }
-+
-+    TRACE_SPAKE_SEND_SUPPORT(context);
-+    return convert_to_padata(support, pa_out);
-+}
-+
-+/* Return true if SF-NONE is present in factors. */
-+static krb5_boolean
-+contains_sf_none(krb5_spake_factor **factors)
-+{
-+    int i;
-+
-+    for (i = 0; factors != NULL && factors[i] != NULL; i++) {
-+        if (factors[i]->type == SPAKE_SF_NONE)
-+            return TRUE;
-+    }
-+    return FALSE;
-+}
-+
-+static krb5_error_code
-+process_challenge(krb5_context context, groupstate *gstate, reqstate *st,
-+                  krb5_spake_challenge *ch, const krb5_data *der_msg,
-+                  krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock,
-+                  krb5_prompter_fct prompter, void *prompter_data,
-+                  const krb5_data *der_req, krb5_pa_data ***pa_out)
-+{
-+    krb5_error_code ret;
-+    krb5_keyblock *k0 = NULL, *k1 = NULL;
-+    krb5_spake_factor factor;
-+    krb5_pa_spake msg;
-+    krb5_data *der_factor = NULL, *response;
-+    krb5_data clpriv = empty_data(), clpub = empty_data();
-+    krb5_data wbytes = empty_data();
-+    krb5_enc_data enc_factor;
-+
-+    enc_factor.ciphertext = empty_data();
-+
-+    /* Not expected if we already computed the SPAKE result. */
-+    if (st->spakeresult.length != 0)
-+        return KRB5KDC_ERR_PREAUTH_FAILED;
-+
-+    if (!group_is_permitted(gstate, ch->group)) {
-+        TRACE_SPAKE_REJECT_CHALLENGE(context, ch->group);
-+        /* No point in sending a second support message. */
-+        if (st->support != NULL)
-+            return KRB5KDC_ERR_PREAUTH_FAILED;
-+        return send_support(context, gstate, st, pa_out);
-+    }
-+
-+    /* Initialize and update the transcript with the concatenation of the
-+     * support message (if we sent one) and the received challenge. */
-+    ret = update_thash(context, gstate, ch->group, &st->thash, st->support,
-+                       der_msg);
-+    if (ret)
-+        return ret;
-+
-+    TRACE_SPAKE_RECEIVE_CHALLENGE(context, ch->group, &ch->pubkey);
-+
-+    /* When second factor support is implemented, we should check for a
-+     * supported factor type instead of just checking for SF-NONE. */
-+    if (!contains_sf_none(ch->factors))
-+        return KRB5KDC_ERR_PREAUTH_FAILED;
-+
-+    ret = derive_wbytes(context, ch->group, st->initial_key, &wbytes);
-+    if (ret)
-+        goto cleanup;
-+    ret = group_keygen(context, gstate, ch->group, &wbytes, &clpriv, &clpub);
-+    if (ret)
-+        goto cleanup;
-+    ret = group_result(context, gstate, ch->group, &wbytes, &clpriv,
-+                       &ch->pubkey, &st->spakeresult);
-+    if (ret)
-+        goto cleanup;
-+
-+    ret = update_thash(context, gstate, ch->group, &st->thash, &clpub, NULL);
-+    if (ret)
-+        goto cleanup;
-+    TRACE_SPAKE_CLIENT_THASH(context, &st->thash);
-+
-+    /* Replace the reply key with K'[0]. */
-+    ret = derive_key(context, gstate, ch->group, st->initial_key, &wbytes,
-+                     &st->spakeresult, &st->thash, der_req, 0, &k0);
-+    if (ret)
-+        goto cleanup;
-+    ret = cb->set_as_key(context, rock, k0);
-+    if (ret)
-+        goto cleanup;
-+
-+    /* Encrypt a SPAKESecondFactor message with K'[1]. */
-+    ret = derive_key(context, gstate, ch->group, st->initial_key, &wbytes,
-+                     &st->spakeresult, &st->thash, der_req, 1, &k1);
-+    if (ret)
-+        goto cleanup;
-+    /* When second factor support is implemented, we should construct an
-+     * appropriate factor here instead of hardcoding SF-NONE. */
-+    factor.type = SPAKE_SF_NONE;
-+    factor.data = NULL;
-+    ret = encode_krb5_spake_factor(&factor, &der_factor);
-+    if (ret)
-+        goto cleanup;
-+    ret = krb5_encrypt_helper(context, k1, KRB5_KEYUSAGE_SPAKE, der_factor,
-+                              &enc_factor);
-+    if (ret)
-+        goto cleanup;
-+
-+    /* Encode and output a response message. */
-+    msg.choice = SPAKE_MSGTYPE_RESPONSE;
-+    msg.u.response.pubkey = clpub;
-+    msg.u.response.factor = enc_factor;
-+    ret = encode_krb5_pa_spake(&msg, &response);
-+    if (ret)
-+        goto cleanup;
-+    TRACE_SPAKE_SEND_RESPONSE(context);
-+    ret = convert_to_padata(response, pa_out);
-+
-+cleanup:
-+    krb5_free_keyblock(context, k0);
-+    krb5_free_keyblock(context, k1);
-+    krb5_free_data_contents(context, &enc_factor.ciphertext);
-+    krb5_free_data_contents(context, &clpub);
-+    zapfree(clpriv.data, clpriv.length);
-+    zapfree(wbytes.data, wbytes.length);
-+    if (der_factor != NULL) {
-+        zapfree(der_factor->data, der_factor->length);
-+        free(der_factor);
-+    }
-+    return ret;
-+}
-+
-+static krb5_error_code
-+process_encdata(krb5_context context, reqstate *st, krb5_enc_data *enc,
-+                krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock,
-+                krb5_prompter_fct prompter, void *prompter_data,
-+                const krb5_data *der_prev_req, const krb5_data *der_req,
-+                krb5_pa_data ***pa_out)
-+{
-+    /* Not expected if we haven't sent a response yet. */
-+    if (st->spakeresult.length == 0)
-+        return KRB5KDC_ERR_PREAUTH_FAILED;
-+
-+    /*
-+     * When second factor support is implemented, we should process encdata
-+     * messages according to the factor type.  We should make sure to re-derive
-+     * K'[0] and replace the reply key again, in case the request has changed.
-+     * We should use der_prev_req to derive K'[n] to decrypt factor from the
-+     * KDC.  We should use der_req to derive K'[n+1] for the next message to
-+     * send to the KDC.
-+     */
-+    return KRB5_PLUGIN_OP_NOTSUPP;
-+}
-+
-+static krb5_error_code
-+spake_process(krb5_context context, krb5_clpreauth_moddata moddata,
-+              krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt,
-+              krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock,
-+              krb5_kdc_req *req, krb5_data *der_req, krb5_data *der_prev_req,
-+              krb5_pa_data *pa_in, krb5_prompter_fct prompter,
-+              void *prompter_data, krb5_pa_data ***pa_out)
-+{
-+    krb5_error_code ret;
-+    groupstate *gstate = (groupstate *)moddata;
-+    reqstate *st = (reqstate *)modreq;
-+    krb5_pa_spake *msg;
-+    krb5_data in_data;
-+    krb5_keyblock *as_key;
-+
-+    if (st == NULL)
-+        return ENOMEM;
-+
-+    if (pa_in->length == 0) {
-+        /* Not expected if we already sent a support message. */
-+        if (st->support != NULL)
-+            return KRB5KDC_ERR_PREAUTH_FAILED;
-+        return send_support(context, gstate, st, pa_out);
-+    }
-+
-+    /* We need the initial reply key to process any non-trivial message. */
-+    if (st->initial_key == NULL) {
-+        ret = cb->get_as_key(context, rock, &as_key);
-+        if (ret)
-+            return ret;
-+        ret = krb5_copy_keyblock(context, as_key, &st->initial_key);
-+        if (ret)
-+            return ret;
-+    }
-+
-+    in_data = make_data(pa_in->contents, pa_in->length);
-+    ret = decode_krb5_pa_spake(&in_data, &msg);
-+    if (ret)
-+        return ret;
-+
-+    if (msg->choice == SPAKE_MSGTYPE_CHALLENGE) {
-+        ret = process_challenge(context, gstate, st, &msg->u.challenge,
-+                                &in_data, cb, rock, prompter, prompter_data,
-+                                der_req, pa_out);
-+    } else if (msg->choice == SPAKE_MSGTYPE_ENCDATA) {
-+        ret = process_encdata(context, st, &msg->u.encdata, cb, rock, prompter,
-+                              prompter_data, der_prev_req, der_req, pa_out);
-+    } else {
-+        /* Unexpected message type */
-+        ret = KRB5KDC_ERR_PREAUTH_FAILED;
-+    }
-+
-+    k5_free_pa_spake(context, msg);
-+    return ret;
-+}
-+
-+krb5_error_code
-+clpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
-+                       krb5_plugin_vtable vtable);
-+
-+krb5_error_code
-+clpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
-+                       krb5_plugin_vtable vtable)
-+{
-+    krb5_clpreauth_vtable vt;
-+    static krb5_preauthtype pa_types[] = { KRB5_PADATA_SPAKE, 0 };
-+
-+    if (maj_ver != 1)
-+        return KRB5_PLUGIN_VER_NOTSUPP;
-+    vt = (krb5_clpreauth_vtable)vtable;
-+    vt->name = "spake";
-+    vt->pa_type_list = pa_types;
-+    vt->init = spake_init;
-+    vt->fini = spake_fini;
-+    vt->request_init = spake_request_init;
-+    vt->request_fini = spake_request_fini;
-+    vt->process = spake_process;
-+    vt->prep_questions = spake_prep_questions;
-+    return 0;
-+}
-diff --git a/src/plugins/preauth/spake/spake_kdc.c b/src/plugins/preauth/spake/spake_kdc.c
-new file mode 100644
-index 000000000..c1723ebaf
---- /dev/null
-+++ b/src/plugins/preauth/spake/spake_kdc.c
-@@ -0,0 +1,590 @@
-+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-+/* plugins/preauth/spake/spake_kdc.c - SPAKE kdcpreauth module */
-+/*
-+ * Copyright (C) 2015 by the Massachusetts Institute of Technology.
-+ * 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.
-+ *
-+ * 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 HOLDER 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 "k5-int.h"
-+#include "k5-input.h"
-+#include "k5-spake.h"
-+
-+#include "groups.h"
-+#include "trace.h"
-+#include "iana.h"
-+#include "util.h"
-+
-+#include <krb5/kdcpreauth_plugin.h>
-+
-+/*
-+ * The SPAKE kdcpreauth module uses a secure cookie containing the following
-+ * concatenated fields (all integer fields are big-endian):
-+ *
-+ *     version (16-bit unsigned integer)
-+ *     stage (16-bit unsigned integer)
-+ *     group (32-bit signed integer)
-+ *     SPAKE value (32-bit unsigned length, followed by data)
-+ *     Transcript hash (32-bit unsigned length, followed by data)
-+ *     Zero or more instances of:
-+ *         second-factor number (32-bit signed integer)
-+ *         second-factor data (32-bit unsigned length, followed by data)
-+ *
-+ * The only currently supported version is 1.  stage is 0 if the cookie was
-+ * sent with a challenge message.  stage is n>0 if the cookie was sent with an
-+ * encdata message encrypted in K'[2n].  group indicates the group number used
-+ * in the SPAKE challenge.  The SPAKE value is the KDC private key for a
-+ * stage-0 cookie, represented in the scalar marshalling form of the group; for
-+ * other cookies, the SPAKE value is the SPAKE result K, represented in the
-+ * group element marshalling form.  The transcript hash is the intermediate
-+ * hash after updating with the support and challenge messages for a stage-0
-+ * cookie, or the final hash for other cookies.  For a stage 0 cookie, there
-+ * may be any number of second-factor records, including none (no record is
-+ * generated for SF-NONE); for other cookies, there must be exactly one
-+ * second-factor record corresponding to the factor type chosen by the client.
-+ */
-+
-+/* From a k5input structure representing the remainder of a secure cookie
-+ * plaintext, parse a four-byte length and data. */
-+static void
-+parse_data(struct k5input *in, krb5_data *out)
-+{
-+    out->length = k5_input_get_uint32_be(in);
-+    out->data = (char *)k5_input_get_bytes(in, out->length);
-+}
-+
-+/* Parse a received cookie into its components.  The pointers stored in the
-+ * krb5_data outputs are aliases into cookie and should not be freed. */
-+static krb5_error_code
-+parse_cookie(const krb5_data *cookie, int *stage_out, int32_t *group_out,
-+             krb5_data *spake_out, krb5_data *thash_out,
-+             krb5_data *factors_out)
-+{
-+    struct k5input in;
-+    int version, stage;
-+    int32_t group;
-+    krb5_data thash, spake, factors;
-+
-+    *spake_out = *thash_out = *factors_out = empty_data();
-+    k5_input_init(&in, cookie->data, cookie->length);
-+
-+    /* Parse and check the version, and read the other integer fields. */
-+    version = k5_input_get_uint16_be(&in);
-+    if (version != 1)
-+        return KRB5KDC_ERR_PREAUTH_FAILED;
-+    stage = k5_input_get_uint16_be(&in);
-+    group = k5_input_get_uint32_be(&in);
-+
-+    /* Parse the data fields.  The factor data is anything remaining after the
-+     * transcript hash. */
-+    parse_data(&in, &spake);
-+    parse_data(&in, &thash);
-+    if (in.status)
-+        return in.status;
-+    factors = make_data((char *)in.ptr, in.len);
-+
-+    *stage_out = stage;
-+    *group_out = group;
-+    *spake_out = spake;
-+    *thash_out = thash;
-+    *factors_out = factors;
-+    return 0;
-+}
-+
-+/* Marshal data into buf as a four-byte length followed by the contents. */
-+static void
-+marshal_data(struct k5buf *buf, const krb5_data *data)
-+{
-+    uint8_t lenbuf[4];
-+
-+    store_32_be(data->length, lenbuf);
-+    k5_buf_add_len(buf, lenbuf, 4);
-+    k5_buf_add_len(buf, data->data, data->length);
-+}
-+
-+/* Marshal components into a cookie. */
-+static krb5_error_code
-+make_cookie(int stage, int32_t group, const krb5_data *spake,
-+            const krb5_data *thash, krb5_data *cookie_out)
-+{
-+    struct k5buf buf;
-+    uint8_t intbuf[4];
-+
-+    *cookie_out = empty_data();
-+    k5_buf_init_dynamic_zap(&buf);
-+
-+    /* Marshal the version, stage, and group. */
-+    store_16_be(1, intbuf);
-+    k5_buf_add_len(&buf, intbuf, 2);
-+    store_16_be(stage, intbuf);
-+    k5_buf_add_len(&buf, intbuf, 2);
-+    store_32_be(group, intbuf);
-+    k5_buf_add_len(&buf, intbuf, 4);
-+
-+    /* Marshal the data fields. */
-+    marshal_data(&buf, spake);
-+    marshal_data(&buf, thash);
-+
-+    /* When second factor support is implemented, we should add factor data
-+     * here. */
-+
-+    if (buf.data == NULL)
-+        return ENOMEM;
-+    *cookie_out = make_data(buf.data, buf.len);
-+    return 0;
-+}
-+
-+/* Add authentication indicators if any are configured for SPAKE. */
-+static krb5_error_code
-+add_indicators(krb5_context context, const krb5_data *realm,
-+               krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock)
-+{
-+    krb5_error_code ret;
-+    const char *keys[4];
-+    char *realmstr, **indicators, **ind;
-+
-+    realmstr = k5memdup0(realm->data, realm->length, &ret);
-+    if (realmstr == NULL)
-+        return ret;
-+    keys[0] = KRB5_CONF_REALMS;
-+    keys[1] = realmstr;
-+    keys[2] = KRB5_CONF_SPAKE_PREAUTH_INDICATOR;
-+    keys[3] = NULL;
-+    ret = profile_get_values(context->profile, keys, &indicators);
-+    free(realmstr);
-+    if (ret == PROF_NO_RELATION)
-+        return 0;
-+    if (ret)
-+        return ret;
-+
-+    for (ind = indicators; *ind != NULL && !ret; ind++)
-+        ret = cb->add_auth_indicator(context, rock, *ind);
-+
-+    profile_free_list(indicators);
-+    return ret;
-+}
-+
-+/* Initialize a SPAKE module data object. */
-+static krb5_error_code
-+spake_init(krb5_context context, krb5_kdcpreauth_moddata *moddata_out,
-+           const char **realmnames)
-+{
-+    krb5_error_code ret;
-+    groupstate *gstate;
-+
-+    ret = group_init_state(context, TRUE, &gstate);
-+    if (ret)
-+        return ret;
-+    *moddata_out = (krb5_kdcpreauth_moddata)gstate;
-+    return 0;
-+}
-+
-+/* Release a SPAKE module data object. */
-+static void
-+spake_fini(krb5_context context, krb5_kdcpreauth_moddata moddata)
-+{
-+    group_free_state((groupstate *)moddata);
-+}
-+
-+/*
-+ * Generate a SPAKE challenge message for the specified group.  Use cb and rock
-+ * to retrieve the initial reply key and to set a stage-0 cookie.  Invoke
-+ * either erespond or vrespond with the result.
-+ */
-+static void
-+send_challenge(krb5_context context, groupstate *gstate, int32_t group,
-+               krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
-+               const krb5_data *support,
-+               krb5_kdcpreauth_edata_respond_fn erespond,
-+               krb5_kdcpreauth_verify_respond_fn vrespond, void *arg)
-+{
-+    krb5_error_code ret;
-+    const krb5_keyblock *ikey;
-+    krb5_pa_data **padata = NULL, *pa;
-+    krb5_data kdcpriv = empty_data(), kdcpub = empty_data(), *der_msg = NULL;
-+    krb5_data thash = empty_data(), cookie = empty_data();
-+    krb5_data wbytes = empty_data();
-+    krb5_spake_factor f, *flist[2];
-+    krb5_pa_spake msg;
-+
-+    ikey = cb->client_keyblock(context, rock);
-+    if (ikey == NULL) {
-+        ret = KRB5KDC_ERR_ETYPE_NOSUPP;
-+        goto cleanup;
-+    }
-+
-+    ret = derive_wbytes(context, group, ikey, &wbytes);
-+    if (ret)
-+        goto cleanup;
-+    ret = group_keygen(context, gstate, group, &wbytes, &kdcpriv, &kdcpub);
-+    if (ret)
-+        goto cleanup;
-+
-+    /* Encode the challenge.  When second factor support is implemented, we
-+     * should construct a factor list instead of hardcoding SF-NONE. */
-+    f.type = SPAKE_SF_NONE;
-+    f.data = NULL;
-+    flist[0] = &f;
-+    flist[1] = NULL;
-+    msg.choice = SPAKE_MSGTYPE_CHALLENGE;
-+    msg.u.challenge.group = group;
-+    msg.u.challenge.pubkey = kdcpub;
-+    msg.u.challenge.factors = flist;
-+    ret = encode_krb5_pa_spake(&msg, &der_msg);
-+    if (ret)
-+        goto cleanup;
-+
-+    /* Initialize and update the transcript hash with the support message (if
-+     * we received one) and challenge message. */
-+    ret = update_thash(context, gstate, group, &thash, support, der_msg);
-+    if (ret)
-+        goto cleanup;
-+
-+    /* Save the group, transcript hash, and private key in a stage-0 cookie.
-+     * When second factor support is implemented, also save factor state. */
-+    ret = make_cookie(0, group, &kdcpriv, &thash, &cookie);
-+    if (ret)
-+        goto cleanup;
-+    ret = cb->set_cookie(context, rock, KRB5_PADATA_SPAKE, &cookie);
-+    if (ret)
-+        goto cleanup;
-+
-+    ret = convert_to_padata(der_msg, &padata);
-+    der_msg = NULL;
-+    TRACE_SPAKE_SEND_CHALLENGE(context, group);
-+
-+cleanup:
-+    zapfree(wbytes.data, wbytes.length);
-+    zapfree(kdcpriv.data, kdcpriv.length);
-+    zapfree(cookie.data, cookie.length);
-+    krb5_free_data_contents(context, &kdcpub);
-+    krb5_free_data_contents(context, &thash);
-+    krb5_free_data(context, der_msg);
-+
-+    if (erespond != NULL) {
-+        assert(vrespond == NULL);
-+        /* Grab the first pa-data element from the list, if we made one. */
-+        pa = (padata == NULL) ? NULL : padata[0];
-+        free(padata);
-+        (*erespond)(arg, ret, pa);
-+    } else {
-+        assert(vrespond != NULL);
-+        if (!ret)
-+            ret = KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED;
-+        (*vrespond)(arg, ret, NULL, padata, NULL);
-+    }
-+}
-+
-+/* Generate the METHOD-DATA entry indicating support for SPAKE.  Include an
-+ * optimistic challenge if configured to do so. */
-+static void
-+spake_edata(krb5_context context, krb5_kdc_req *req,
-+            krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
-+            krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type,
-+            krb5_kdcpreauth_edata_respond_fn respond, void *arg)
-+{
-+    const krb5_keyblock *ikey;
-+    groupstate *gstate = (groupstate *)moddata;
-+    krb5_data empty = empty_data();
-+    int32_t group;
-+
-+    /* SPAKE requires a client key, which cannot be a single-DES key. */
-+    ikey = cb->client_keyblock(context, rock);
-+    if (ikey == NULL) {
-+        (*respond)(arg, KRB5KDC_ERR_ETYPE_NOSUPP, NULL);
-+        return;
-+    }
-+
-+    group = group_optimistic_challenge(gstate);
-+    if (group) {
-+        send_challenge(context, gstate, group, cb, rock, &empty, respond, NULL,
-+                       arg);
-+    } else {
-+        /* No optimistic challenge configured; send an empty pa-data value. */
-+        (*respond)(arg, 0, NULL);
-+    }
-+}
-+
-+/* Choose a group from the client's support message and generate a
-+ * challenge. */
-+static void
-+verify_support(krb5_context context, groupstate *gstate,
-+               krb5_spake_support *support, const krb5_data *der_msg,
-+               krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
-+               krb5_kdcpreauth_verify_respond_fn respond, void *arg)
-+{
-+    krb5_error_code ret;
-+    int32_t i, group;
-+
-+    for (i = 0; i < support->ngroups; i++) {
-+        if (group_is_permitted(gstate, support->groups[i]))
-+            break;
-+    }
-+    if (i == support->ngroups) {
-+        TRACE_SPAKE_REJECT_SUPPORT(context);
-+        ret = KRB5KDC_ERR_PREAUTH_FAILED;
-+        goto error;
-+    }
-+    group = support->groups[i];
-+    TRACE_SPAKE_RECEIVE_SUPPORT(context, group);
-+
-+    send_challenge(context, gstate, group, cb, rock, der_msg, NULL, respond,
-+                   arg);
-+    return;
-+
-+error:
-+    (*respond)(arg, ret, NULL, NULL, NULL);
-+}
-+
-+/*
-+ * From the client's response message, compute the SPAKE result and decrypt the
-+ * factor reply.  On success, either mark the reply as pre-authenticated and
-+ * set a reply key in the pre-request module data, or generate an additional
-+ * factor challenge and ask for another round of pre-authentication.
-+ */
-+static void
-+verify_response(krb5_context context, groupstate *gstate,
-+                krb5_spake_response *resp, const krb5_data *realm,
-+                krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
-+                krb5_enc_tkt_part *enc_tkt_reply,
-+                krb5_kdcpreauth_verify_respond_fn respond, void *arg)
-+{
-+    krb5_error_code ret;
-+    const krb5_keyblock *ikey;
-+    krb5_keyblock *k1 = NULL, *reply_key = NULL;
-+    krb5_data cookie, thash_in, kdcpriv, factors, *der_req;
-+    krb5_data thash = empty_data(), der_factor = empty_data();
-+    krb5_data wbytes = empty_data(), spakeresult = empty_data();
-+    krb5_spake_factor *factor = NULL;
-+    int stage;
-+    int32_t group;
-+
-+    ikey = cb->client_keyblock(context, rock);
-+    if (ikey == NULL) {
-+        ret = KRB5KDC_ERR_ETYPE_NOSUPP;
-+        goto cleanup;
-+    }
-+
-+    /* Fetch the stage-0 cookie and parse it.  (All of the krb5_data results
-+     * are aliases into memory owned by rock). */
-+    if (!cb->get_cookie(context, rock, KRB5_PADATA_SPAKE, &cookie)) {
-+        ret = KRB5KDC_ERR_PREAUTH_FAILED;
-+        goto cleanup;
-+    }
-+    ret = parse_cookie(&cookie, &stage, &group, &kdcpriv, &thash_in, &factors);
-+    if (ret)
-+        goto cleanup;
-+    if (stage != 0) {
-+        /* The received cookie wasn't sent with a challenge. */
-+        ret = KRB5KDC_ERR_PREAUTH_FAILED;
-+        goto cleanup;
-+    }
-+    TRACE_SPAKE_RECEIVE_RESPONSE(context, &resp->pubkey);
-+
-+    /* Update the transcript hash with the client public key. */
-+    ret = krb5int_copy_data_contents(context, &thash_in, &thash);
-+    if (ret)
-+        goto cleanup;
-+    ret = update_thash(context, gstate, group, &thash, &resp->pubkey, NULL);
-+    if (ret)
-+        goto cleanup;
-+    TRACE_SPAKE_KDC_THASH(context, &thash);
-+
-+    ret = derive_wbytes(context, group, ikey, &wbytes);
-+    if (ret)
-+        goto cleanup;
-+    ret = group_result(context, gstate, group, &wbytes, &kdcpriv,
-+                       &resp->pubkey, &spakeresult);
-+    if (ret)
-+        goto cleanup;
-+
-+    /* Decrypt the response factor field using K'[1].  If the decryption
-+     * integrity check fails, the client probably used the wrong password. */
-+    der_req = cb->request_body(context, rock);
-+    ret = derive_key(context, gstate, group, ikey, &wbytes, &spakeresult,
-+                     &thash, der_req, 1, &k1);
-+    if (ret)
-+        goto cleanup;
-+    ret = alloc_data(&der_factor, resp->factor.ciphertext.length);
-+    if (ret)
-+        goto cleanup;
-+    ret = krb5_c_decrypt(context, k1, KRB5_KEYUSAGE_SPAKE, NULL, &resp->factor,
-+                         &der_factor);
-+    if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY)
-+        ret = KRB5KDC_ERR_PREAUTH_FAILED;
-+    if (ret)
-+        goto cleanup;
-+    ret = decode_krb5_spake_factor(&der_factor, &factor);
-+    if (ret)
-+        goto cleanup;
-+
-+    /*
-+     * When second factor support is implemented, we should verify the factor
-+     * data here, and possibly generate an encdata message for another hop.
-+     * This function may need to be split at this point to allow for
-+     * asynchronous verification of the second-factor value.  We might also
-+     * need to collect authentication indicators from the second-factor module;
-+     * alternatively the module could have access to cb and rock so that it can
-+     * add indicators itself.
-+     */
-+    if (factor->type != SPAKE_SF_NONE) {
-+        ret = KRB5KDC_ERR_PREAUTH_FAILED;
-+        goto cleanup;
-+    }
-+
-+    ret = add_indicators(context, realm, cb, rock);
-+    if (ret)
-+        goto cleanup;
-+
-+    enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH;
-+
-+    ret = derive_key(context, gstate, group, ikey, &wbytes, &spakeresult,
-+                     &thash, der_req, 0, &reply_key);
-+
-+cleanup:
-+    zapfree(wbytes.data, wbytes.length);
-+    zapfree(der_factor.data, der_factor.length);
-+    zapfree(spakeresult.data, spakeresult.length);
-+    krb5_free_data_contents(context, &thash);
-+    krb5_free_keyblock(context, k1);
-+    k5_free_spake_factor(context, factor);
-+    (*respond)(arg, ret, (krb5_kdcpreauth_modreq)reply_key, NULL, NULL);
-+}
-+
-+/*
-+ * Decrypt and validate an additional second-factor reply.  On success, either
-+ * mark the reply as pre-authenticated and set a reply key in the pre-request
-+ * module data, or generate an additional factor challenge and ask for another
-+ * round of pre-authentication.
-+ */
-+static void
-+verify_encdata(krb5_context context, krb5_enc_data *enc,
-+               krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
-+               krb5_enc_tkt_part *enc_tkt_reply,
-+               krb5_kdcpreauth_verify_respond_fn respond, void *arg)
-+{
-+    /*
-+     * When second factor support is implemented, we should process encdata
-+     * message according to the factor type recorded in the cookie.  If the
-+     * second factor exchange finishes successfully, we should set
-+     * TKT_FLG_PRE_AUTH, set the reply key to K'[0], and add any auth
-+     * indicators from configuration (with a call to add_indicators()) or the
-+     * second factor module (unless the module has access to cb and rock and
-+     * can add indicators itself).
-+     */
-+    (*respond)(arg, KRB5KDC_ERR_PREAUTH_FAILED, NULL, NULL, NULL);
-+}
-+
-+/*
-+ * Respond to a client padata message, either by generating a SPAKE challenge,
-+ * generating an additional second-factor challenge, or marking the reply as
-+ * pre-authenticated and setting an additional reply key in the pre-request
-+ * module data.
-+ */
-+static void
-+spake_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request,
-+             krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *data,
-+             krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
-+             krb5_kdcpreauth_moddata moddata,
-+             krb5_kdcpreauth_verify_respond_fn respond, void *arg)
-+{
-+    krb5_error_code ret;
-+    krb5_pa_spake *pa_spake = NULL;
-+    krb5_data in_data = make_data(data->contents, data->length);
-+    groupstate *gstate = (groupstate *)moddata;
-+
-+    ret = decode_krb5_pa_spake(&in_data, &pa_spake);
-+    if (ret) {
-+        (*respond)(arg, ret, NULL, NULL, NULL);
-+    } else if (pa_spake->choice == SPAKE_MSGTYPE_SUPPORT) {
-+        verify_support(context, gstate, &pa_spake->u.support, &in_data, cb,
-+                       rock, respond, arg);
-+    } else if (pa_spake->choice == SPAKE_MSGTYPE_RESPONSE) {
-+        verify_response(context, gstate, &pa_spake->u.response,
-+                        &request->server->realm, cb, rock, enc_tkt_reply,
-+                        respond, arg);
-+    } else if (pa_spake->choice == SPAKE_MSGTYPE_ENCDATA) {
-+        verify_encdata(context, &pa_spake->u.encdata, cb, rock, enc_tkt_reply,
-+                       respond, arg);
-+    } else {
-+        ret = KRB5KDC_ERR_PREAUTH_FAILED;
-+        k5_setmsg(context, ret, _("Unknown SPAKE request type"));
-+        (*respond)(arg, ret, NULL, NULL, NULL);
-+    }
-+
-+    k5_free_pa_spake(context, pa_spake);
-+}
-+
-+/* If a key was set in the per-request module data, replace the reply key.  Do
-+ * not generate any pa-data to include with the KDC reply. */
-+static krb5_error_code
-+spake_return(krb5_context context, krb5_pa_data *padata, krb5_data *req_pkt,
-+             krb5_kdc_req *request, krb5_kdc_rep *reply,
-+             krb5_keyblock *encrypting_key, krb5_pa_data **send_pa_out,
-+             krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
-+             krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq)
-+{
-+    krb5_keyblock *reply_key = (krb5_keyblock *)modreq;
-+
-+    if (reply_key == NULL)
-+        return 0;
-+    krb5_free_keyblock_contents(context, encrypting_key);
-+    return krb5_copy_keyblock_contents(context, reply_key, encrypting_key);
-+}
-+
-+/* Release a per-request module data object. */
-+static void
-+spake_free_modreq(krb5_context context, krb5_kdcpreauth_moddata moddata,
-+                  krb5_kdcpreauth_modreq modreq)
-+{
-+    krb5_free_keyblock(context, (krb5_keyblock *)modreq);
-+}
-+
-+krb5_error_code
-+kdcpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
-+                        krb5_plugin_vtable vtable);
-+
-+krb5_error_code
-+kdcpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
-+                        krb5_plugin_vtable vtable)
-+{
-+    krb5_kdcpreauth_vtable vt;
-+    static krb5_preauthtype pa_types[] = { KRB5_PADATA_SPAKE, 0 };
-+
-+    if (maj_ver != 1)
-+        return KRB5_PLUGIN_VER_NOTSUPP;
-+    vt = (krb5_kdcpreauth_vtable)vtable;
-+    vt->name = "spake";
-+    vt->pa_type_list = pa_types;
-+    vt->init = spake_init;
-+    vt->fini = spake_fini;
-+    vt->edata = spake_edata;
-+    vt->verify = spake_verify;
-+    vt->return_padata = spake_return;
-+    vt->free_modreq = spake_free_modreq;
-+    return 0;
-+}
-diff --git a/src/plugins/preauth/spake/t_krb5.conf b/src/plugins/preauth/spake/t_krb5.conf
-new file mode 100644
-index 000000000..65fdaec63
---- /dev/null
-+++ b/src/plugins/preauth/spake/t_krb5.conf
-@@ -0,0 +1,2 @@
-+[libdefaults]
-+	spake_preauth_groups = edwards25519
-diff --git a/src/plugins/preauth/spake/t_vectors.c b/src/plugins/preauth/spake/t_vectors.c
-new file mode 100644
-index 000000000..2279202d3
---- /dev/null
-+++ b/src/plugins/preauth/spake/t_vectors.c
-@@ -0,0 +1,476 @@
-+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-+/* plugins/preauth/spake/t_vectors.c - SPAKE test vector verification */
-+/*
-+ * Copyright (C) 2015 by the Massachusetts Institute of Technology.
-+ * 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.
-+ *
-+ * 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 HOLDER 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 "k5-int.h"
-+#include "k5-hex.h"
-+#include "groups.h"
-+#include "iana.h"
-+#include "util.h"
-+#include <ctype.h>
-+
-+struct test {
-+    krb5_enctype enctype;
-+    int32_t group;
-+    const char *ikey;
-+    const char *w;
-+    const char *x;
-+    const char *y;
-+    const char *T;
-+    const char *S;
-+    const char *K;
-+    const char *support;
-+    const char *challenge;
-+    const char *thash;
-+    const char *body;
-+    const char *K0;
-+    const char *K1;
-+    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",
-+      "7C86659D29CF2B2EA93BFE79C3CEFB8850E82215B3EA6FCD896561D48048F49C",
-+      "C8A62E7B626F44CAD807B2D695450697E020D230A738C5CD5691CC781DCE8754",
-+      "18FE7C1512708C7FD06DB270361F04593775BC634CEAF45347E5C11C38AAE017",
-+      "7DB465F1C08C64983A19F560BCE966FE5306C4B447F70A5BCA14612A92DA1D63",
-+      "38F8D4568090148EBC9FD17C241B4CC2769505A7CA6F3F7104417B72B5B5CF54",
-+      "03E75EDD2CD7E7677642DD68736E91700953AC55DC650E3C2A1B3B4ACDB800F8",
-+      /* support, challenge, thash, body */
-+      "A0093007A0053003020101",
-+      "A1363034A003020101A12204207DB465F1C08C64983A19F560BCE966FE5306C4"
-+      "B447F70A5BCA14612A92DA1D63A20930073005A003020101",
-+      "F4B208458017DE6EF7F6A307D47D87DB6C2AF1D291B726860F68BC08BFEF440A",
-+      "3075A00703050000000000A1143012A003020101A10B30091B07726165627572"
-+      "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018"
-+      "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730"
-+      "303130313030303030305AA703020100A8053003020117",
-+      /* K'[0], K'[1], K'[2], K'[3] */
-+      "770B720C82384CBB693E85411EEDECBA",
-+      "621DEEC88E2865837C4D3462BB50A1D5",
-+      "1CC8F6333B9FA3B42662FD9914FBD5BB",
-+      "EDB4032B7FC3806D5211A534DCBC390C",
-+    },
-+
-+    { ENCTYPE_AES128_CTS_HMAC_SHA1_96, SPAKE_GROUP_EDWARDS25519,
-+      /* initial key, w, x, y, T, S, K */
-+      "FCA822951813FB252154C883F5EE1CF4",
-+      "0D591B197B667E083C2F5F98AC891D3C9F99E710E464E62F1FB7C9B67936F3EB",
-+      "50BE049A5A570FA1459FB9F666E6FD80602E4E87790A0E567F12438A2C96C138",
-+      "B877AFE8612B406D96BE85BD9F19D423E95BE96C0E1E0B5824127195C3ED5917",
-+      "9E9311D985C1355E022D7C3C694AD8D6F7AD6D647B68A90B0FE46992818002DA",
-+      "FBE08F7F96CD5D4139E7C9ECCB95E79B8ACE41E270A60198C007DF18525B628E",
-+      "C2F7F99997C585E6B686CEB62DB42F17CC70932DEF3BB4CF009E36F22EA5473D",
-+      /* support, challenge, thash, body */
-+      "A0093007A0053003020101",
-+      "A1363034A003020101A12204209E9311D985C1355E022D7C3C694AD8D6F7AD6D"
-+      "647B68A90B0FE46992818002DAA20930073005A003020101",
-+      "951285F107C87F0169B9C918A1F51F60CB1A75B9F8BB799A99F53D03ADD94B5F",
-+      "3075A00703050000000000A1143012A003020101A10B30091B07726165627572"
-+      "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018"
-+      "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730"
-+      "303130313030303030305AA703020100A8053003020111",
-+      /* K'[0], K'[1], K'[2], K'[3] */
-+      "548022D58A7C47EAE8C49DCCF6BAA407",
-+      "B2C9BA0E13FC8AB3A9D96B51B601CF4A",
-+      "69F0EE5FDB6C237E7FCD38D9F87DF1BD",
-+      "78F91E2240B5EE528A5CC8D7CBEBFBA5",
-+    },
-+    { ENCTYPE_AES256_CTS_HMAC_SHA1_96, SPAKE_GROUP_EDWARDS25519,
-+      /* initial key, w, x, y, T, S, K */
-+      "01B897121D933AB44B47EB5494DB15E50EB74530DBDAE9B634D65020FF5D88C1",
-+      "E902341590A1B4BB4D606A1C643CCCB3F2108F1B6AA97B381012B9400C9E3F4E",
-+      "88C6C0A4F0241EF217C9788F02C32D00B72E4310748CD8FB5F94717607E6417D",
-+      "88B859DF58EF5C69BACDFE681C582754EAAB09A74DC29CFF50B328613C232F55",
-+      "6F301AACAE1220E91BE42868C163C5009AEEA1E9D9E28AFCFC339CDA5E7105B5",
-+      "9E2CC32908FC46273279EC75354B4AEAFA70C3D99A4D507175ED70D80B255DDA",
-+      "CF57F58F6E60169D2ECC8F20BB923A8E4C16E5BC95B9E64B5DC870DA7026321B",
-+      /* support, challenge, thash, body */
-+      "A0093007A0053003020101",
-+      "A1363034A003020101A12204206F301AACAE1220E91BE42868C163C5009AEEA1"
-+      "E9D9E28AFCFC339CDA5E7105B5A20930073005A003020101",
-+      "1C605649D4658B58CBE79A5FAF227ACC16C355C58B7DADE022F90C158FE5ED8E",
-+      "3075A00703050000000000A1143012A003020101A10B30091B07726165627572"
-+      "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018"
-+      "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730"
-+      "303130313030303030305AA703020100A8053003020112",
-+      /* K'[0], K'[1], K'[2], K'[3] */
-+      "A9BFA71C95C575756F922871524B65288B3F695573CCC0633E87449568210C23",
-+      "1865A9EE1EF0640EC28AC007391CAC624C42639C714767A974E99AA10003015F",
-+      "E57781513FEFDB978E374E156B0DA0C1A08148F5EB26B8E157AC3C077E28BF49",
-+      "008E6487293C3CC9FABBBCDD8B392D6DCB88222317FD7FE52D12FBC44FA047F1",
-+    },
-+
-+#ifdef SPAKE_OPENSSL
-+    { ENCTYPE_AES256_CTS_HMAC_SHA1_96, SPAKE_GROUP_P256,
-+      /* initial key, w, x, y, T, S, K */
-+      "01B897121D933AB44B47EB5494DB15E50EB74530DBDAE9B634D65020FF5D88C1",
-+      "EB2984AF18703F94DD5288B8596CD36988D0D4E83BFB2B44DE14D0E95E2090BD",
-+      "935DDD725129FB7C6288E1A5CC45782198A6416D1775336D71EACD0549A3E80E",
-+      "E07405EB215663ABC1F254B8ADC0DA7A16FEBAA011AF923D79FDEF7C42930B33",
-+      "024F62078CEB53840D02612195494D0D0D88DE21FEEB81187C71CBF3D01E71788D",
-+      "021D07DC31266FC7CFD904CE2632111A169B7EC730E5F74A7E79700F86638E13C8",
-+      "0268489D7A9983F2FDE69C6E6A1307E9D252259264F5F2DFC32F58CCA19671E79B",
-+      /* support, challenge, thash, body */
-+      "A0093007A0053003020102",
-+      "A1373035A003020102A1230421024F62078CEB53840D02612195494D0D0D88DE"
-+      "21FEEB81187C71CBF3D01E71788DA20930073005A003020101",
-+      "20AD3C1A9A90FC037D1963A1C4BFB15AB4484D7B6CF07B12D24984F14652DE60",
-+      "3075A00703050000000000A1143012A003020101A10B30091B07726165627572"
-+      "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018"
-+      "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730"
-+      "303130313030303030305AA703020100A8053003020112",
-+      /* K'[0], K'[1], K'[2], K'[3] */
-+      "7D3B906F7BE49932DB22CD3463F032D06C9C078BE4B1D076D201FC6E61EF531E",
-+      "17D74E36F8993841FBB7FEB12FA4F011243D3AE4D2ACE55B39379294BBC4DB2C",
-+      "D192C9044081A2AA6A97A6C69E2724E8E5671C2C9CE073DD439CDBAF96D7DAB0",
-+      "41E5BAD6B67F12C53CE0E2720DD6A9887F877BF9463C2D5209C74C36F8D776B7",
-+    },
-+
-+    { ENCTYPE_AES256_CTS_HMAC_SHA1_96, SPAKE_GROUP_P384,
-+      /* initial key, w, x, y, T, S, K */
-+      "01B897121D933AB44B47EB5494DB15E50EB74530DBDAE9B634D65020FF5D88C1",
-+      "0304CFC55151C6BBE889653DB96DBFE0BA4ACAFC024C1E8840CB3A486F6D80C1"
-+      "6E1B8974016AA4B7FA43042A9B3825B1",
-+      "F323CA74D344749096FD35D0ADF20806E521460637176E84D977E9933C49D76F"
-+      "CFC6E62585940927468FF53D864A7A50",
-+      "5B7C709ACB175A5AFB82860DEABCA8D0B341FACDFF0AC0F1A425799AA905D750"
-+      "7E1EA9C573581A81467437419466E472",
-+      "02A1524603EF14F184696F854229D3397507A66C63F841BA748451056BE07879"
-+      "AC298912387B1C5CDFF6381C264701BE57",
-+      "020D5ADFDB92BC377041CF5837412574C5D13E0F4739208A4F0C859A0A302BC6"
-+      "A533440A245B9D97A0D34AF5016A20053D",
-+      "0264AA8C61DA9600DFB0BEB5E46550D63740E4EF29E73F1A30D543EB43C25499"
-+      "037AD16538586552761B093CF0E37C703A",
-+      /* support, challenge, thash, body */
-+      "A0093007A0053003020103",
-+      "A1473045A003020103A133043102A1524603EF14F184696F854229D3397507A6"
-+      "6C63F841BA748451056BE07879AC298912387B1C5CDFF6381C264701BE57A209"
-+      "30073005A003020101",
-+      "5AC0D99EF9E5A73998797FE64F074673E3952DEC4C7D1AACCE8B75F64D2B0276"
-+      "A901CB8539B4E8ED69E4DB0CE805B47B",
-+      "3075A00703050000000000A1143012A003020101A10B30091B07726165627572"
-+      "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018"
-+      "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730"
-+      "303130313030303030305AA703020100A8053003020112",
-+      /* K'[0], K'[1], K'[2], K'[3] */
-+      "B917D37C16DD1D8567FBE379F64E1EE36CA3FD127AA4E60F97E4AFA3D9E56D91",
-+      "93D40079DAB229B9C79366829F4E7E7282E6A4B943AC7BAC69922D516673F49A",
-+      "BFC4F16F12F683E71589F9A888E232875EF293AC9793DB6C919567CD7B94BCD4",
-+      "3630E2B5B99938E7506733141E8EC344166F6407E5FC2EF107C156E764D1BC20",
-+    },
-+
-+    { ENCTYPE_AES256_CTS_HMAC_SHA1_96, SPAKE_GROUP_P521,
-+      /* initial key, w, x, y, T, S, K */
-+      "01B897121D933AB44B47EB5494DB15E50EB74530DBDAE9B634D65020FF5D88C1",
-+      "DE3A095A2B2386EFF3EB15B735398DA1CAF95BC8425665D82370AFF58B0471F3"
-+      "4A57BCCDDF1EBF0A2965B58A93EE5B45E85D1A5435D1C8C83662999722D54283"
-+      "1F9A",
-+      "017C38701A14B490B6081DFC83524562BE7FBB42E0B20426465E3E37952D30BC"
-+      "AB0ED857010255D44936A1515607964A870C7C879B741D878F9F9CDF5A865306"
-+      "F3F5",
-+      "003E2E2950656FA231E959ACDD984D125E7FA59CEC98126CBC8F3888447911EB"
-+      "CD49428A1C22D5FDB76A19FBEB1D9EDFA3DA6CF55B158B53031D05D51433ADE9"
-+      "B2B4",
-+      "02017D3DE19A3EC53D0174905665EF37947D142535102CD9809C0DFBD0DFE007"
-+      "353D54CF406CE2A59950F2BB540DF6FBE75F8BBBEF811C9BA06CC275ADBD9675"
-+      "6696EC",
-+      "02004D142D87477841F6BA053C8F651F3395AD264B7405CA5911FB9A55ABD454"
-+      "FEF658A5F9ED97D1EFAC68764E9092FA15B9E0050880D78E95FD03ABF5931791"
-+      "6822B5",
-+      "03007C303F62F09282CC849490805BD4457A6793A832CBEB55DF427DB6A31E99"
-+      "B055D5DC99756D24D47B70AD8B6015B0FB8742A718462ED423B90FA3FE631AC1"
-+      "3FA916",
-+      /* support, challenge, thash, body */
-+      "A0093007A0053003020104",
-+      "A1593057A003020104A145044302017D3DE19A3EC53D0174905665EF37947D14"
-+      "2535102CD9809C0DFBD0DFE007353D54CF406CE2A59950F2BB540DF6FBE75F8B"
-+      "BBEF811C9BA06CC275ADBD96756696ECA20930073005A003020101",
-+      "8D6A89AE4D80CC4E47B6F4E48EA3E57919CC69598D0D3DC7C8BD49B6F1DB1409"
-+      "CA0312944CD964E213ABA98537041102237CFF5B331E5347A0673869B412302E",
-+      "3075A00703050000000000A1143012A003020101A10B30091B07726165627572"
-+      "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018"
-+      "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730"
-+      "303130313030303030305AA703020100A8053003020112",
-+      /* K'[0], K'[1], K'[2], K'[3] */
-+      "1EB3D10BEE8FAB483ADCD3EB38F3EBF1F4FEB8DB96ECC035F563CF2E1115D276",
-+      "482B92781CE57F49176E4C94153CC622FE247A7DBE931D1478315F856F085890",
-+      "A2C215126DD3DF280AAB5A27E1E0FB7E594192CBFF8D6D8E1B6F1818D9BB8FAC",
-+      "CC06603DE984324013A01F888DE6D43B410A4DA2DEA53509F30E433C352FB668",
-+    },
-+#endif /* SPAKE_OPENSSL */
-+
-+    /* Successful optimistic challenge (no support message in transcript) */
-+    { ENCTYPE_AES256_CTS_HMAC_SHA1_96, SPAKE_GROUP_EDWARDS25519,
-+      /* initial key, w, x, y, T, S, K */
-+      "01B897121D933AB44B47EB5494DB15E50EB74530DBDAE9B634D65020FF5D88C1",
-+      "E902341590A1B4BB4D606A1C643CCCB3F2108F1B6AA97B381012B9400C9E3F4E",
-+      "70937207344CAFBC53C8A55070E399C584CBAFCE00B836980DD4E7E74FAD2A64",
-+      "785D6801A2490DF028903AC6449B105F2FF0DB895B252953CDC2076649526103",
-+      "83523B35F1565006CBFC4F159885467C2FB9BC6FE23D36CB1DA43D199F1A3118",
-+      "2A8F70F46CEE9030700037B77F22CEC7970DCC238E3E066D9D726BAF183992C6",
-+      "D3C5E4266AA6D1B2873A97CE8AF91C7E4D7A7AC456ACCED7908D34C561AD8FA6",
-+      /* support, challenge, thash, body */
-+      NULL,
-+      "A1363034A003020101A122042083523B35F1565006CBFC4F159885467C2FB9BC"
-+      "6FE23D36CB1DA43D199F1A3118A20930073005A003020101",
-+      "26F07F9F8965307434D11EA855461D41E0CBABCC0A1BAB48ECEE0C6C1A4292B7",
-+      "3075A00703050000000000A1143012A003020101A10B30091B07726165627572"
-+      "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018"
-+      "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730"
-+      "303130313030303030305AA703020100A8053003020112",
-+      /* K'[0], K'[1], K'[2], K'[3] */
-+      "4569EC08B5DE5C3CC19D941725913ACE8D74524B521A341DC746ACD5C3784D92",
-+      "0D96CE1A4AC0F2E280A0CFC31742B06461D83D04AE45433DB2D80478DD882A4C",
-+      "58018C19315A1BA5D5BB9813B58029F0AEC18A6F9CA59E0847DE1C60BC25945C",
-+      "ED7E9BFFD68C54D86FB19CD3C03F317F88A71AD9A5E94C28581D93FC4EC72B6A",
-+    },
-+
-+#ifdef SPAKE_OPENSSL
-+    /* Rejected optimistic challenge (no support message in transcript),
-+     * falling back from edwards25519 to P-521 */
-+    { ENCTYPE_AES256_CTS_HMAC_SHA1_96, SPAKE_GROUP_P521,
-+      /* initial key, w, x, y, T, S, K */
-+      "01B897121D933AB44B47EB5494DB15E50EB74530DBDAE9B634D65020FF5D88C1",
-+      "DE3A095A2B2386EFF3EB15B735398DA1CAF95BC8425665D82370AFF58B0471F3"
-+      "4A57BCCDDF1EBF0A2965B58A93EE5B45E85D1A5435D1C8C83662999722D54283"
-+      "1F9A",
-+      "01687B59051BF40048D7C31D5A973D792FA12284B7A447E7F5938B5885CA0BB2"
-+      "C3F0BD30291A55FEA08E143E2E04BDD7D19B753C7C99032F06CAB0D9C2AA8F83"
-+      "7EF7",
-+      "01DED675EBF74FE30C9A53710F577E9CF84F09F6048FE245A4600004884CC167"
-+      "733F9A9E43108FB83BABE8754CD37CBD7025E28BC9FF870F084C7244F536285E"
-+      "25B4",
-+      "02014CB2E5B592ECE5990F0EF30D308C061DE1598BC4272B4A6599BED466FD15"
-+      "21693642ABCF4DBE36CE1A2D13967DE45F6C4F8D0FA8E14428BF03FB96EF5F1E"
-+      "D3E645",
-+      "02016C64995E804416F748FD5FA3AA678CBC7CBB596A4F523132DC8AF7CE84E5"
-+      "41F484A2C74808C6B21DCF7775BAEFA6753398425BECC7B838B210AC5DAA0CB0"
-+      "B710E2",
-+      "0200997F4848AE2E7A98C23D14AC662030743AB37FCCC2A45F1C721114F40BCC"
-+      "80FE6EC6ABA49868F8AEA1AA994D50E81B86D3E4D3C1130C8695B68907C673D9"
-+      "E5886A",
-+      /* support, challenge, thash, body */
-+      "A0093007A0053003020104",
-+      "A1593057A003020104A145044302014CB2E5B592ECE5990F0EF30D308C061DE1"
-+      "598BC4272B4A6599BED466FD1521693642ABCF4DBE36CE1A2D13967DE45F6C4F"
-+      "8D0FA8E14428BF03FB96EF5F1ED3E645A20930073005A003020101",
-+      "D0EFED5E3E2C39C26034756D92A66FEC3082AD793D0197F3F89AD36026F146A3"
-+      "996E548AA3FC49E2E82F8CAC5D132C505AA475B39E7BE79CDED22C26C41AA777",
-+      "3075A00703050000000000A1143012A003020101A10B30091B07726165627572"
-+      "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018"
-+      "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730"
-+      "303130313030303030305AA703020100A8053003020112",
-+      /* K'[0], K'[1], K'[2], K'[3] */
-+      "631FCC8596E7F40E59045950D72AA0B7BAC2810A07B767050E983841CF3A2D4C",
-+      "881464920117074DBC67155A8F3341D1121EF65F78EA0380BFA81A134C1C47B1",
-+      "377B72AC3AF2CAAD582D73AE4682FD56B531EE56706200DD6C38C42B8219837A",
-+      "35AD8E4D580ED3F0D15AD928329773C081BD19F9A56363F3A5F77C7E66108C26",
-+    },
-+#endif /* SPAKE_OPENSSL */
-+};
-+
-+static krb5_context ctx;
-+
-+static void
-+check(krb5_error_code code)
-+{
-+    const char *errmsg;
-+
-+    if (code) {
-+        errmsg = krb5_get_error_message(ctx, code);
-+        assert(errmsg != NULL);
-+        abort();
-+    }
-+}
-+
-+static void
-+check_key_equal(const krb5_keyblock *kb1, const krb5_keyblock *kb2)
-+{
-+    assert(kb1->enctype == kb2->enctype);
-+    assert(kb1->length == kb2->length);
-+    assert(memcmp(kb1->contents, kb2->contents, kb1->length) == 0);
-+}
-+
-+static krb5_data *
-+decode_data(const char *s)
-+{
-+    uint8_t *bytes;
-+    size_t len;
-+    krb5_data *d;
-+
-+    if (k5_hex_decode(s, &bytes, &len) != 0)
-+        abort();
-+    d = malloc(sizeof(*d));
-+    assert(d != NULL);
-+    *d = make_data(bytes, len);
-+    return d;
-+}
-+
-+static krb5_keyblock *
-+decode_keyblock(krb5_enctype enctype, const char *s)
-+{
-+    uint8_t *bytes;
-+    size_t len;
-+    krb5_keyblock *kb;
-+
-+    if (k5_hex_decode(s, &bytes, &len) != 0)
-+        abort();
-+    kb = malloc(sizeof(*kb));
-+    kb->magic = KV5M_KEYBLOCK;
-+    kb->enctype = enctype;
-+    kb->length = len;
-+    kb->contents = bytes;
-+    return kb;
-+}
-+
-+static void
-+run_test(const struct test *t)
-+{
-+    groupstate *gstate;
-+    krb5_keyblock *ikey, *K0, *K1, *K2, *K3, *kb;
-+    krb5_data *w, *x, *y, *T, *S, *K, *support, *challenge, *thash;
-+    krb5_data *body, wbytes, result, hash, empty = empty_data();
-+
-+    /* Decode hex strings into keyblocks and byte strings. */
-+    ikey = decode_keyblock(t->enctype, t->ikey);
-+    w = decode_data(t->w);
-+    x = decode_data(t->x);
-+    y = decode_data(t->y);
-+    T = decode_data(t->T);
-+    S = decode_data(t->S);
-+    K = decode_data(t->K);
-+    support = (t->support != NULL) ? decode_data(t->support) : NULL;
-+    challenge = decode_data(t->challenge);
-+    thash = decode_data(t->thash);
-+    body = decode_data(t->body);
-+    K0 = decode_keyblock(t->enctype, t->K0);
-+    K1 = decode_keyblock(t->enctype, t->K1);
-+    K2 = decode_keyblock(t->enctype, t->K2);
-+    K3 = decode_keyblock(t->enctype, t->K3);
-+
-+    check(derive_wbytes(ctx, t->group, ikey, &wbytes));
-+    assert(data_eq(*w, wbytes));
-+
-+    /* Verify KDC-side result computation. */
-+    check(group_init_state(ctx, TRUE, &gstate));
-+    check(group_result(ctx, gstate, t->group, &wbytes, x, S, &result));
-+    assert(data_eq(*K, result));
-+    krb5_free_data_contents(ctx, &result);
-+    group_free_state(gstate);
-+
-+    /* Verify client-side result computation. */
-+    check(group_init_state(ctx, FALSE, &gstate));
-+    check(group_result(ctx, gstate, t->group, &wbytes, y, T, &result));
-+    assert(data_eq(*K, result));
-+    krb5_free_data_contents(ctx, &result);
-+
-+    /* Verify transcript hash. */
-+    hash = empty_data();
-+    check(update_thash(ctx, gstate, t->group, &hash, support, challenge));
-+    check(update_thash(ctx, gstate, t->group, &hash, S, &empty));
-+    assert(data_eq(*thash, hash));
-+    krb5_free_data_contents(ctx, &hash);
-+
-+    /* Verify derived keys. */
-+    check(derive_key(ctx, gstate, t->group, ikey, &wbytes, K, thash, body, 0,
-+                     &kb));
-+    check_key_equal(K0, kb);
-+    krb5_free_keyblock(ctx, kb);
-+    check(derive_key(ctx, gstate, t->group, ikey, &wbytes, K, thash, body, 1,
-+                     &kb));
-+    check_key_equal(K1, kb);
-+    krb5_free_keyblock(ctx, kb);
-+    check(derive_key(ctx, gstate, t->group, ikey, &wbytes, K, thash, body, 2,
-+                     &kb));
-+    check_key_equal(K2, kb);
-+    krb5_free_keyblock(ctx, kb);
-+    check(derive_key(ctx, gstate, t->group, ikey, &wbytes, K, thash, body, 3,
-+                     &kb));
-+    check_key_equal(K3, kb);
-+    krb5_free_keyblock(ctx, kb);
-+
-+    group_free_state(gstate);
-+    krb5_free_data_contents(ctx, &wbytes);
-+    krb5_free_keyblock(ctx, ikey);
-+    krb5_free_data(ctx, w);
-+    krb5_free_data(ctx, x);
-+    krb5_free_data(ctx, y);
-+    krb5_free_data(ctx, T);
-+    krb5_free_data(ctx, S);
-+    krb5_free_data(ctx, K);
-+    krb5_free_data(ctx, support);
-+    krb5_free_data(ctx, challenge);
-+    krb5_free_data(ctx, thash);
-+    krb5_free_data(ctx, body);
-+    krb5_free_keyblock(ctx, K0);
-+    krb5_free_keyblock(ctx, K1);
-+    krb5_free_keyblock(ctx, K2);
-+    krb5_free_keyblock(ctx, K3);
-+}
-+
-+int
-+main()
-+{
-+    size_t i;
-+
-+    check(krb5_init_context(&ctx));
-+    for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
-+        run_test(&tests[i]);
-+    krb5_free_context(ctx);
-+    return 0;
-+}
-diff --git a/src/plugins/preauth/spake/trace.h b/src/plugins/preauth/spake/trace.h
-new file mode 100644
-index 000000000..9dd964260
---- /dev/null
-+++ b/src/plugins/preauth/spake/trace.h
-@@ -0,0 +1,74 @@
-+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-+/* plugins/preauth/spake/internal.h - SPAKE internal function declarations */
-+/*
-+ * Copyright (C) 2015 by the Massachusetts Institute of Technology.
-+ * 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.
-+ *
-+ * 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 HOLDER 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.
-+ */
-+
-+#ifndef TRACE_H
-+#define TRACE_H
-+
-+#include "k5-int.h"
-+
-+/*
-+ * Possible improvements at the cost of more code:
-+ * - Groups could be displayed by name instead of number
-+ * - We could display the group list when tracing support messages
-+ */
-+
-+#define TRACE_SPAKE_CLIENT_THASH(c, thash)                      \
-+    TRACE(c, "SPAKE final transcript hash: {hexdata}", thash)
-+#define TRACE_SPAKE_DERIVE_KEY(c, n, kb)                        \
-+    TRACE(c, "SPAKE derived K'[{int}] = {keyblock}", n, kb)
-+#define TRACE_SPAKE_KDC_THASH(c, thash)                         \
-+    TRACE(c, "SPAKE final transcript hash: {hexdata}", thash)
-+#define TRACE_SPAKE_KEYGEN(c, pubkey)                                   \
-+    TRACE(c, "SPAKE key generated with pubkey {hexdata}", pubkey)
-+#define TRACE_SPAKE_RECEIVE_CHALLENGE(c, group, pubkey)                 \
-+    TRACE(c, "SPAKE challenge received with group {int}, pubkey {hexdata}", \
-+          group, pubkey)
-+#define TRACE_SPAKE_RECEIVE_RESPONSE(c, pubkey)                         \
-+    TRACE(c, "SPAKE response received with pubkey {hexdata}", pubkey)
-+#define TRACE_SPAKE_RECEIVE_SUPPORT(c, group)                           \
-+    TRACE(c, "SPAKE support message received, selected group {int}", group)
-+#define TRACE_SPAKE_REJECT_CHALLENGE(c, group)                          \
-+    TRACE(c, "SPAKE challenge with group {int} rejected", (int)group)
-+#define TRACE_SPAKE_REJECT_SUPPORT(c)           \
-+    TRACE(c, "SPAKE support message rejected")
-+#define TRACE_SPAKE_RESULT(c, result)                           \
-+    TRACE(c, "SPAKE algorithm result: {hexdata}", result)
-+#define TRACE_SPAKE_SEND_CHALLENGE(c, group)                    \
-+    TRACE(c, "Sending SPAKE challenge with group {int}", group)
-+#define TRACE_SPAKE_SEND_RESPONSE(c)            \
-+    TRACE(c, "Sending SPAKE response")
-+#define TRACE_SPAKE_SEND_SUPPORT(c)             \
-+    TRACE(c, "Sending SPAKE support message")
-+#define TRACE_SPAKE_UNKNOWN_GROUP(c, name)                      \
-+    TRACE(c, "Unrecognized SPAKE group name: {string}", name)
-+
-+#endif /* TRACE_H */
-diff --git a/src/plugins/preauth/spake/util.c b/src/plugins/preauth/spake/util.c
-new file mode 100644
-index 000000000..cbdbbd7ac
---- /dev/null
-+++ b/src/plugins/preauth/spake/util.c
-@@ -0,0 +1,211 @@
-+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-+/* plugins/preauth/spake/util.c - Utility functions for SPAKE preauth module */
-+/*
-+ * Copyright (C) 2015 by the Massachusetts Institute of Technology.
-+ * 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.
-+ *
-+ * 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 HOLDER 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 "k5-int.h"
-+#include "trace.h"
-+#include "util.h"
-+#include "groups.h"
-+
-+/* Use data to construct a single-element pa-data list of type
-+ * KRB5_PADATA_SPAKE.  Claim data's memory on success or failure. */
-+krb5_error_code
-+convert_to_padata(krb5_data *data, krb5_pa_data ***pa_out)
-+{
-+    krb5_pa_data *pa = NULL, **list = NULL;
-+
-+    list = calloc(2, sizeof(*list));
-+    if (list == NULL)
-+        goto fail;
-+    pa = calloc(1, sizeof(*pa));
-+    if (pa == NULL)
-+        goto fail;
-+    pa->magic = KV5M_PA_DATA;
-+    pa->pa_type = KRB5_PADATA_SPAKE;
-+    pa->length = data->length;
-+    pa->contents = (uint8_t *)data->data;
-+    list[0] = pa;
-+    list[1] = NULL;
-+    *pa_out = list;
-+    free(data);
-+    return 0;
-+
-+fail:
-+    free(list);
-+    free(pa);
-+    free(data->data);
-+    free(data);
-+    return ENOMEM;
-+}
-+
-+/*
-+ * Update the transcript hash thash with its current value and the
-+ * concatenation of data1 and data2, using the hash function for group.  Either
-+ * data1 or data2 may be NULL to omit it.  Allocate thash if it is empty.
-+ */
-+krb5_error_code
-+update_thash(krb5_context context, groupstate *gstate, int32_t group,
-+             krb5_data *thash, const krb5_data *data1, const krb5_data *data2)
-+{
-+    krb5_error_code ret;
-+    size_t hashlen;
-+    krb5_data dlist[3];
-+
-+    if (thash->length == 0) {
-+        /* Initialize the transcript hash to all zeros. */
-+        ret = group_hash_len(group, &hashlen);
-+        if (ret)
-+            return ret;
-+        ret = alloc_data(thash, hashlen);
-+        if (ret)
-+            return ret;
-+    }
-+
-+    /* Set up the data array and hash it with the group's hash function. */
-+    dlist[0] = *thash;
-+    dlist[1] = (data1 != NULL) ? *data1 : empty_data();
-+    dlist[2] = (data2 != NULL) ? *data2 : empty_data();
-+    return group_hash(context, gstate, group, dlist, 3,
-+                      (uint8_t *)thash->data);
-+}
-+
-+/* Derive a byte vector for the SPAKE w multiplier input from ikey.  Place
-+ * result in allocated storage in *wbytes_out. */
-+krb5_error_code
-+derive_wbytes(krb5_context context, int32_t group, const krb5_keyblock *ikey,
-+              krb5_data *wbytes_out)
-+{
-+    krb5_error_code ret;
-+    const char prefix[] = "SPAKEsecret";
-+    size_t mult_len, prefix_len = sizeof(prefix) - 1;
-+    krb5_data prf_input = empty_data(), wbytes = empty_data();
-+
-+    *wbytes_out = empty_data();
-+
-+    /* Allocate space for a multiplier. */
-+    ret = group_mult_len(group, &mult_len);
-+    if (ret)
-+        goto cleanup;
-+    ret = alloc_data(&wbytes, mult_len);
-+    if (ret)
-+        goto cleanup;
-+
-+    /* Compose the PRF input string. */
-+    ret = alloc_data(&prf_input, prefix_len + 4);
-+    if (ret)
-+        goto cleanup;
-+    memcpy(prf_input.data, prefix, prefix_len);
-+    store_32_be(group, prf_input.data + prefix_len);
-+
-+    /* Derive the SPAKE input from the initial reply key with PRF+. */
-+    ret = krb5_c_prfplus(context, ikey, &prf_input, &wbytes);
-+    if (ret)
-+        goto cleanup;
-+
-+    *wbytes_out = wbytes;
-+    wbytes = empty_data();
-+
-+cleanup:
-+    free(prf_input.data);
-+    zapfree(wbytes.data, wbytes.length);
-+    return ret;
-+}
-+
-+/*
-+ * Derive K'[n] from the group number, the initial key enctype, the initial
-+ * multiplier, the SPAKE result, the transcript hash, and the encoded
-+ * KDC-REQ-BODY.  Place the result in allocated storage in *out.
-+ */
-+krb5_error_code
-+derive_key(krb5_context context, groupstate *gstate, int32_t group,
-+           const krb5_keyblock *ikey, const krb5_data *wbytes,
-+           const krb5_data *spakeresult, const krb5_data *thash,
-+           const krb5_data *der_req, uint32_t n, krb5_keyblock **out)
-+{
-+    krb5_error_code ret;
-+    krb5_data dlist[9], seed = empty_data(), d;
-+    uint8_t groupnbuf[4], etypenbuf[4], nbuf[4], bcount;
-+    size_t hashlen, seedlen, keylen, nblocks, i;
-+    size_t ndata = sizeof(dlist) / sizeof(*dlist);
-+    krb5_keyblock *hkey = NULL;
-+
-+    *out = NULL;
-+
-+    store_32_be(group, groupnbuf);
-+    store_32_be(n, nbuf);
-+    store_32_be(ikey->enctype, etypenbuf);
-+    dlist[0] = string2data("SPAKEkey");
-+    dlist[1] = make_data(groupnbuf, sizeof(groupnbuf));
-+    dlist[2] = make_data(etypenbuf, sizeof(etypenbuf));
-+    dlist[3] = *wbytes;
-+    dlist[4] = *spakeresult;
-+    dlist[5] = *thash;
-+    dlist[6] = *der_req;
-+    dlist[7] = make_data(nbuf, sizeof(nbuf));
-+    dlist[8] = make_data(&bcount, 1);
-+
-+    /* Count the number of hash blocks required (should be 1 for all current
-+     * scenarios) and allocate space. */
-+    ret = group_hash_len(group, &hashlen);
-+    if (ret)
-+        goto cleanup;
-+    ret = krb5_c_keylengths(context, ikey->enctype, &seedlen, &keylen);
-+    if (ret)
-+        goto cleanup;
-+    nblocks = (seedlen + hashlen - 1) / hashlen;
-+    ret = alloc_data(&seed, nblocks * hashlen);
-+    if (ret)
-+        goto cleanup;
-+
-+    /* Compute and concatenate hash blocks to fill the seed buffer. */
-+    for (i = 0; i < nblocks; i++) {
-+        bcount = i + 1;
-+        ret = group_hash(context, gstate, group, dlist, ndata,
-+                         (uint8_t *)seed.data + i * hashlen);
-+        if (ret)
-+            goto cleanup;
-+    }
-+
-+    ret = krb5_init_keyblock(context, ikey->enctype, keylen, &hkey);
-+    if (ret)
-+        goto cleanup;
-+    d = make_data(seed.data, seedlen);
-+    ret = krb5_c_random_to_key(context, ikey->enctype, &d, hkey);
-+    if (ret)
-+        goto cleanup;
-+
-+    ret = krb5_c_fx_cf2_simple(context, ikey, "SPAKE", hkey, "keyderiv", out);
-+
-+cleanup:
-+    zapfree(seed.data, seed.length);
-+    krb5_free_keyblock(context, hkey);
-+    return ret;
-+}
-diff --git a/src/plugins/preauth/spake/util.h b/src/plugins/preauth/spake/util.h
-new file mode 100644
-index 000000000..3ab2bead1
---- /dev/null
-+++ b/src/plugins/preauth/spake/util.h
-@@ -0,0 +1,56 @@
-+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-+/* plugins/preauth/spake/internal.h - SPAKE internal function declarations */
-+/*
-+ * Copyright (C) 2015 by the Massachusetts Institute of Technology.
-+ * 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.
-+ *
-+ * 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 HOLDER 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.
-+ */
-+
-+#ifndef UTIL_H
-+#define UTIL_H
-+
-+#include "k5-int.h"
-+#include "groups.h"
-+
-+krb5_error_code convert_to_padata(krb5_data *data, krb5_pa_data ***pa_out);
-+
-+krb5_error_code update_thash(krb5_context context, groupstate *gstate,
-+                             int32_t group, krb5_data *thash,
-+                             const krb5_data *data1, const krb5_data *data2);
-+
-+krb5_error_code derive_wbytes(krb5_context context, int32_t group,
-+                              const krb5_keyblock *ikey,
-+                              krb5_data *wbytes_out);
-+
-+krb5_error_code derive_key(krb5_context context, groupstate *gstate,
-+                           int32_t group, const krb5_keyblock *ikey,
-+                           const krb5_data *wbytes,
-+                           const krb5_data *spakeresult,
-+                           const krb5_data *thash, const krb5_data *der_req,
-+                           uint32_t n, krb5_keyblock **out);
-+
-+#endif /* UTIL_H */
-diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
-index 67d3e8200..aed23e570 100644
---- a/src/tests/Makefile.in
-+++ b/src/tests/Makefile.in
-@@ -130,6 +130,7 @@ check-pytests: unlockiter
- 	$(RUNPYTEST) $(srcdir)/t_changepw.py $(PYTESTFLAGS)
- 	$(RUNPYTEST) $(srcdir)/t_pkinit.py $(PYTESTFLAGS)
- 	$(RUNPYTEST) $(srcdir)/t_otp.py $(PYTESTFLAGS)
-+	$(RUNPYTEST) $(srcdir)/t_spake.py $(PYTESTFLAGS)
- 	$(RUNPYTEST) $(srcdir)/t_localauth.py $(PYTESTFLAGS)
- 	$(RUNPYTEST) $(srcdir)/t_kadm5_hook.py $(PYTESTFLAGS)
- 	$(RUNPYTEST) $(srcdir)/t_kadm5_auth.py $(PYTESTFLAGS)
-diff --git a/src/tests/t_spake.py b/src/tests/t_spake.py
-new file mode 100644
-index 000000000..a81a238b4
---- /dev/null
-+++ b/src/tests/t_spake.py
-@@ -0,0 +1,151 @@
-+#!/usr/bin/python
-+from k5test import *
-+
-+# The name and number of each supported SPAKE group.
-+builtin_groups = ((1, 'edwards25519'),)
-+openssl_groups = ((2, 'P-256'), (3, 'P-384'), (4, 'P-521'))
-+if runenv.have_spake_openssl == 'yes':
-+    groups = builtin_groups + openssl_groups
-+else:
-+    groups = builtin_groups
-+
-+for gnum, gname in groups:
-+    output('*** Testing group %s\n' % gname)
-+    conf = {'libdefaults': {'spake_preauth_groups': gname}}
-+    for realm in multipass_realms(create_user=False, create_host=False,
-+                                  krb5_conf=conf):
-+        realm.run([kadminl, 'addprinc', '+preauth', '-pw', 'pw', 'user'])
-+
-+        # Test a basic SPAKE preauth scenario with no optimizations.
-+        msgs = ('Sending unauthenticated request',
-+                '/Additional pre-authentication required',
-+                'Selected etype info:',
-+                'Sending SPAKE support message',
-+                'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)',
-+                '/More preauthentication data is required',
-+                'Continuing preauth mech PA-SPAKE (151)',
-+                'SPAKE challenge received with group ' + str(gnum),
-+                'Sending SPAKE response',
-+                'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)',
-+                'AS key determined by preauth:',
-+                'Decrypted AS reply')
-+        realm.kinit('user', 'pw', expected_trace=msgs)
-+
-+        # Test an unsuccessful authentication.  (The client will try
-+        # again with encrypted timestamp, which isn't really desired,
-+        # but check for that as long as it is expected.)
-+        msgs = ('/Additional pre-authentication required',
-+                'Selected etype info:',
-+                'Sending SPAKE support message',
-+                'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)',
-+                '/More preauthentication data is required',
-+                'Continuing preauth mech PA-SPAKE (151)',
-+                'SPAKE challenge received with group ' + str(gnum),
-+                'Sending SPAKE response',
-+                '/Preauthentication failed',
-+                'Encrypted timestamp ',
-+                'for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)',
-+                '/Preauthentication failed')
-+        realm.kinit('user', 'wrongpw', expected_code=1, expected_trace=msgs)
-+
-+conf = {'libdefaults': {'spake_preauth_groups': 'edwards25519'}}
-+kdcconf = {'realms': {'$realm': {'spake_preauth_indicator': 'indspake'}}}
-+realm = K5Realm(create_user=False, krb5_conf=conf, kdc_conf=kdcconf)
-+realm.run([kadminl, 'addprinc', '+preauth', '-pw', 'pw', 'user'])
-+
-+# Test with FAST.
-+msgs = ('Using FAST due to armor ccache negotiation',
-+        'FAST armor key:',
-+        'Sending unauthenticated request',
-+        '/Additional pre-authentication required',
-+        'Decoding FAST response',
-+        'Selected etype info:',
-+        'Sending SPAKE support message',
-+        'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)',
-+        '/More preauthentication data is required',
-+        'Continuing preauth mech PA-SPAKE (151)',
-+        'SPAKE challenge received with group 1',
-+        'Sending SPAKE response',
-+        'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)',
-+        'AS key determined by preauth:',
-+        'FAST reply key:')
-+realm.kinit(realm.host_princ, flags=['-k'])
-+realm.kinit('user', 'pw', flags=['-T', realm.ccache], expected_trace=msgs)
-+
-+# Test optimistic client preauth (151 is PA-SPAKE).
-+msgs = ('Attempting optimistic preauth',
-+        'Processing preauth types: PA-SPAKE (151)',
-+        'Sending SPAKE support message',
-+        'for next request: PA-SPAKE (151)',
-+        '/More preauthentication data is required',
-+        'Selected etype info:',
-+        'SPAKE challenge received with group 1',
-+        'Sending SPAKE response',
-+        'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)',
-+        'AS key determined by preauth:',
-+        'Decrypted AS reply')
-+realm.run(['./icred', '-o', '151', 'user', 'pw'], expected_trace=msgs)
-+
-+# Test KDC optimistic challenge (accepted by client).
-+oconf = {'kdcdefaults': {'spake_preauth_kdc_challenge': 'edwards25519'}}
-+oenv = realm.special_env('ochal', True, krb5_conf=oconf)
-+realm.stop_kdc()
-+realm.start_kdc(env=oenv)
-+msgs = ('Sending unauthenticated request',
-+        '/Additional pre-authentication required',
-+        'Selected etype info:',
-+        'SPAKE challenge received with group 1',
-+        'Sending SPAKE response',
-+        'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)',
-+        'AS key determined by preauth:',
-+        'Decrypted AS reply')
-+realm.kinit('user', 'pw', expected_trace=msgs)
-+
-+if runenv.have_spake_openssl != 'yes':
-+    skip_rest('SPAKE fallback tests', 'SPAKE not built using OpenSSL')
-+
-+# Test optimistic client preauth falling back to encrypted timestamp
-+# because the KDC doesn't support any of the client groups.
-+p256conf={'libdefaults': {'spake_preauth_groups': 'P-256'}}
-+p256env = realm.special_env('p256', False, krb5_conf=p256conf)
-+msgs = ('Attempting optimistic preauth',
-+        'Processing preauth types: PA-SPAKE (151)',
-+        'Sending SPAKE support message',
-+        'for next request: PA-SPAKE (151)',
-+        '/Preauthentication failed',
-+        'Selected etype info:',
-+        'SPAKE challenge with group 1 rejected',
-+        'spake (151) (real) returned: -1765328360/Preauthentication failed',
-+        'Encrypted timestamp ',
-+        'for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)',
-+        'AS key determined by preauth:',
-+        'Decrypted AS reply')
-+realm.run(['./icred', '-o', '151', 'user', 'pw'], env=p256env,
-+          expected_trace=msgs)
-+
-+# Test KDC optimistic challenge (rejected by client).
-+rconf = {'libdefaults': {'spake_preauth_groups': 'P-384,edwards25519'},
-+         'kdcdefaults': {'spake_preauth_kdc_challenge': 'P-384'}}
-+renv = realm.special_env('ochal', True, krb5_conf=rconf)
-+realm.stop_kdc()
-+realm.start_kdc(env=renv)
-+msgs = ('Sending unauthenticated request',
-+        '/Additional pre-authentication required',
-+        'Selected etype info:',
-+        'SPAKE challenge with group 3 rejected',
-+        'Sending SPAKE support message',
-+        'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)',
-+        '/More preauthentication data is required',
-+        'Continuing preauth mech PA-SPAKE (151)',
-+        'SPAKE challenge received with group 1',
-+        'Sending SPAKE response',
-+        'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)',
-+        'AS key determined by preauth:',
-+        'Decrypted AS reply')
-+realm.kinit('user', 'pw', expected_trace=msgs)
-+
-+# Check that the auth indicator for SPAKE is properly included by the KDC.
-+realm.run([kvno, realm.host_princ])
-+realm.run(['./adata', realm.host_princ], expected_msg='+97: [indspake]')
-+
-+success('SPAKE pre-authentication tests')
diff --git a/SOURCES/Add-doc-index-entries-for-SPAKE-constants.patch b/SOURCES/Add-doc-index-entries-for-SPAKE-constants.patch
deleted file mode 100644
index 7ac2afe..0000000
--- a/SOURCES/Add-doc-index-entries-for-SPAKE-constants.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From c891e4bc54c8083a1af8d28aa9b12ab1177ebb9a Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Tue, 27 Mar 2018 00:49:43 -0400
-Subject: [PATCH] Add doc index entries for SPAKE constants
-
-ticket: 8647
-(cherry picked from commit c010c9031753f356bb380e8a1324cc34721f8221)
----
- doc/appdev/refs/macros/index.rst | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst
-index dba818b26..47c6d4413 100644
---- a/doc/appdev/refs/macros/index.rst
-+++ b/doc/appdev/refs/macros/index.rst
-@@ -190,6 +190,7 @@ Public
-    KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM.rst
-    KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID.rst
-    KRB5_KEYUSAGE_PA_SAM_RESPONSE.rst
-+   KRB5_KEYUSAGE_SPAKE.rst
-    KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY.rst
-    KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY.rst
-    KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY.rst
-@@ -274,6 +275,7 @@ Public
-    KRB5_PADATA_SAM_RESPONSE.rst
-    KRB5_PADATA_SAM_RESPONSE_2.rst
-    KRB5_PADATA_SESAME.rst
-+   KRB5_PADATA_SPAKE.rst
-    KRB5_PADATA_SVR_REFERRAL_INFO.rst
-    KRB5_PADATA_TGS_REQ.rst
-    KRB5_PADATA_USE_SPECIFIED_KVNO.rst
diff --git a/SOURCES/Add-flag-to-disable-encrypted-timestamp-on-client.patch b/SOURCES/Add-flag-to-disable-encrypted-timestamp-on-client.patch
deleted file mode 100644
index adc4f41..0000000
--- a/SOURCES/Add-flag-to-disable-encrypted-timestamp-on-client.patch
+++ /dev/null
@@ -1,204 +0,0 @@
-From f44ef4893050e673f495444c27a19525813f75a8 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Mon, 11 Jun 2018 13:53:27 -0400
-Subject: [PATCH] Add flag to disable encrypted timestamp on client
-
-ticket: 8655
-(cherry picked from commit 4ad376134b8d456392edbac7a7d351e6c7a7f0e7)
----
- doc/admin/conf_files/krb5_conf.rst | 10 ++++++++++
- doc/admin/spake.rst                |  8 ++++++++
- src/include/k5-int.h               |  1 +
- src/include/k5-trace.h             |  2 ++
- src/lib/krb5/krb/get_in_tkt.c      | 23 +++++++++++++++++++++++
- src/lib/krb5/krb/init_creds_ctx.h  |  1 +
- src/lib/krb5/krb/preauth_encts.c   | 14 +++++++++++++-
- src/tests/t_referral.py            | 13 +++++++++++++
- 8 files changed, 71 insertions(+), 1 deletion(-)
-
-diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
-index ce545492d..eb5c29e5d 100644
---- a/doc/admin/conf_files/krb5_conf.rst
-+++ b/doc/admin/conf_files/krb5_conf.rst
-@@ -475,6 +475,16 @@ following tags may be specified in the realm's subsection:
-     (for example, when converting ``rcmd.hostname`` to
-     ``host/hostname.domain``).
- 
-+**disable_encrypted_timestamp**
-+    If this flag is true, the client will not perform encrypted
-+    timestamp preauthentication if requested by the KDC.  Setting this
-+    flag can help to prevent dictionary attacks by active attackers,
-+    if the realm's KDCs support SPAKE preauthentication or if initial
-+    authentication always uses another mechanism or always uses FAST.
-+    This flag persists across client referrals during initial
-+    authentication.  This flag does not prevent the KDC from offering
-+    encrypted timestamp.  New in release 1.17.
-+
- **http_anchors**
-     When KDCs and kpasswd servers are accessed through HTTPS proxies, this tag
-     can be used to specify the location of the CA certificate which should be
-diff --git a/doc/admin/spake.rst b/doc/admin/spake.rst
-index b65c694aa..4f6eeaf53 100644
---- a/doc/admin/spake.rst
-+++ b/doc/admin/spake.rst
-@@ -30,6 +30,14 @@ principal entries, as you would for any preauthentication mechanism::
- Clients which do not implement SPAKE preauthentication will fall back
- to encrypted timestamp.
- 
-+An active attacker can force a fallback to encrypted timestamp by
-+modifying the initial KDC response, defeating the protection against
-+dictionary attacks.  To prevent this fallback on clients which do
-+implement SPAKE preauthentication, set the
-+**disable_encrypted_timestamp** variable to ``true`` in the
-+:ref:`realms` subsection for realms whose KDCs offer SPAKE
-+preauthentication.
-+
- By default, SPAKE preauthentication requires an extra network round
- trip to the KDC during initial authentication.  If most of the clients
- in a realm support SPAKE, this extra round trip can be eliminated
-diff --git a/src/include/k5-int.h b/src/include/k5-int.h
-index 86b53c76b..e4a9a1412 100644
---- a/src/include/k5-int.h
-+++ b/src/include/k5-int.h
-@@ -204,6 +204,7 @@ typedef unsigned char   u_char;
- #define KRB5_CONF_DES_CRC_SESSION_SUPPORTED    "des_crc_session_supported"
- #define KRB5_CONF_DICT_FILE                    "dict_file"
- #define KRB5_CONF_DISABLE                      "disable"
-+#define KRB5_CONF_DISABLE_ENCRYPTED_TIMESTAMP  "disable_encrypted_timestamp"
- #define KRB5_CONF_DISABLE_LAST_SUCCESS         "disable_last_success"
- #define KRB5_CONF_DISABLE_LOCKOUT              "disable_lockout"
- #define KRB5_CONF_DNS_CANONICALIZE_HOSTNAME    "dns_canonicalize_hostname"
-diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
-index 5f7eb9517..0854974dc 100644
---- a/src/include/k5-trace.h
-+++ b/src/include/k5-trace.h
-@@ -299,6 +299,8 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
- #define TRACE_PREAUTH_ENC_TS(c, sec, usec, plain, enc)                  \
-     TRACE(c, "Encrypted timestamp (for {long}.{int}): plain {hexdata}, " \
-           "encrypted {hexdata}", (long) sec, (int) usec, plain, enc)
-+#define TRACE_PREAUTH_ENC_TS_DISABLED(c)                                \
-+    TRACE(c, "Ignoring encrypted timestamp because it is disabled")
- #define TRACE_PREAUTH_ETYPE_INFO(c, etype, salt, s2kparams)          \
-     TRACE(c, "Selected etype info: etype {etype}, salt \"{data}\", " \
-           "params \"{data}\"", etype, salt, s2kparams)
-diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
-index c026bbc6d..79dede2c6 100644
---- a/src/lib/krb5/krb/get_in_tkt.c
-+++ b/src/lib/krb5/krb/get_in_tkt.c
-@@ -801,6 +801,24 @@ read_allowed_preauth_type(krb5_context context, krb5_init_creds_context ctx)
-     free(tmp);
- }
- 
-+/* Return true if encrypted timestamp is disabled for realm. */
-+static krb5_boolean
-+encts_disabled(profile_t profile, const krb5_data *realm)
-+{
-+    krb5_error_code ret;
-+    char *realmstr;
-+    int bval;
-+
-+    realmstr = k5memdup0(realm->data, realm->length, &ret);
-+    if (realmstr == NULL)
-+        return FALSE;
-+    ret = profile_get_boolean(profile, KRB5_CONF_REALMS, realmstr,
-+                              KRB5_CONF_DISABLE_ENCRYPTED_TIMESTAMP, FALSE,
-+                              &bval);
-+    free(realmstr);
-+    return (ret == 0) ? bval : FALSE;
-+}
-+
- /**
-  * Throw away any pre-authentication realm state and begin with a
-  * unauthenticated or optimistically authenticated request.  If fast_upgrade is
-@@ -842,6 +860,11 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
-             goto cleanup;
-     }
- 
-+    /* Never set encts_disabled back to false, so it can't be circumvented with
-+     * client realm referrals. */
-+    if (encts_disabled(context->profile, &ctx->request->client->realm))
-+        ctx->encts_disabled = TRUE;
-+
-     krb5_free_principal(context, ctx->request->server);
-     ctx->request->server = NULL;
- 
-diff --git a/src/lib/krb5/krb/init_creds_ctx.h b/src/lib/krb5/krb/init_creds_ctx.h
-index 7ba61e17c..7a6219b1c 100644
---- a/src/lib/krb5/krb/init_creds_ctx.h
-+++ b/src/lib/krb5/krb/init_creds_ctx.h
-@@ -61,6 +61,7 @@ struct _krb5_init_creds_context {
-     krb5_boolean info_pa_permitted;
-     krb5_boolean restarted;
-     krb5_boolean fallback_disabled;
-+    krb5_boolean encts_disabled;
-     struct krb5_responder_context_st rctx;
-     krb5_preauthtype selected_preauth_type;
-     krb5_preauthtype allowed_preauth_type;
-diff --git a/src/lib/krb5/krb/preauth_encts.c b/src/lib/krb5/krb/preauth_encts.c
-index 45bf9da92..345701984 100644
---- a/src/lib/krb5/krb/preauth_encts.c
-+++ b/src/lib/krb5/krb/preauth_encts.c
-@@ -28,6 +28,7 @@
- #include <k5-int.h>
- #include <krb5/clpreauth_plugin.h>
- #include "int-proto.h"
-+#include "init_creds_ctx.h"
- 
- static krb5_error_code
- encts_prep_questions(krb5_context context, krb5_clpreauth_moddata moddata,
-@@ -38,7 +39,10 @@ encts_prep_questions(krb5_context context, krb5_clpreauth_moddata moddata,
-                      krb5_data *encoded_previous_request,
-                      krb5_pa_data *pa_data)
- {
--    cb->need_as_key(context, rock);
-+    krb5_init_creds_context ctx = (krb5_init_creds_context)rock;
-+
-+    if (!ctx->encts_disabled)
-+        cb->need_as_key(context, rock);
-     return 0;
- }
- 
-@@ -51,6 +55,7 @@ encts_process(krb5_context context, krb5_clpreauth_moddata moddata,
-               krb5_prompter_fct prompter, void *prompter_data,
-               krb5_pa_data ***out_padata)
- {
-+    krb5_init_creds_context ctx = (krb5_init_creds_context)rock;
-     krb5_error_code ret;
-     krb5_pa_enc_ts pa_enc;
-     krb5_data *ts = NULL, *enc_ts = NULL;
-@@ -60,6 +65,13 @@ encts_process(krb5_context context, krb5_clpreauth_moddata moddata,
- 
-     enc_data.ciphertext = empty_data();
- 
-+    if (ctx->encts_disabled) {
-+        TRACE_PREAUTH_ENC_TS_DISABLED(context);
-+        k5_setmsg(context, KRB5_PREAUTH_FAILED,
-+                  _("Encrypted timestamp is disabled"));
-+        return KRB5_PREAUTH_FAILED;
-+    }
-+
-     ret = cb->get_as_key(context, rock, &as_key);
-     if (ret)
-         goto cleanup;
-diff --git a/src/tests/t_referral.py b/src/tests/t_referral.py
-index 98fdf2925..e12fdc2e9 100755
---- a/src/tests/t_referral.py
-+++ b/src/tests/t_referral.py
-@@ -126,4 +126,17 @@ r1.klist('user@KRBTEST2.COM', 'krbtgt/KRBTEST2.COM')
- r1.kinit('abc@XYZ', 'pw', ['-E'])
- r1.klist('abc\@XYZ@KRBTEST2.COM', 'krbtgt/KRBTEST2.COM')
- 
-+# Test that disable_encrypted_timestamp persists across client
-+# referrals.  (This test relies on SPAKE not being enabled by default
-+# on the KDC.)
-+r2.run([kadminl, 'modprinc', '+preauth', 'user'])
-+msgs = ('Encrypted timestamp (for ')
-+r1.kinit('user', password('user'), ['-C'], expected_trace=msgs)
-+dconf = {'realms': {'$realm': {'disable_encrypted_timestamp': 'true'}}}
-+denv = r1.special_env('disable_encts', False, krb5_conf=dconf)
-+msgs = ('Ignoring encrypted timestamp because it is disabled',
-+        '/Encrypted timestamp is disabled')
-+r1.kinit('user', None, ['-C'], env=denv, expected_code=1, expected_trace=msgs,
-+         expected_msg='Encrypted timestamp is disabled')
-+
- success('KDC host referral tests')
diff --git a/SOURCES/Add-function-and-enctype-flag-for-deprecations.patch b/SOURCES/Add-function-and-enctype-flag-for-deprecations.patch
new file mode 100644
index 0000000..99290da
--- /dev/null
+++ b/SOURCES/Add-function-and-enctype-flag-for-deprecations.patch
@@ -0,0 +1,183 @@
+From 656fb920da2d6be3c55976320e3e13a69af30c8a 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-k5_buf_add_vfmt-to-k5buf-interface.patch b/SOURCES/Add-k5_buf_add_vfmt-to-k5buf-interface.patch
deleted file mode 100644
index 1a333a7..0000000
--- a/SOURCES/Add-k5_buf_add_vfmt-to-k5buf-interface.patch
+++ /dev/null
@@ -1,119 +0,0 @@
-From 74e1079df0cc6e8932e487455177a69f782b863a Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Thu, 4 Jan 2018 14:35:12 -0500
-Subject: [PATCH] Add k5_buf_add_vfmt to k5buf interface
-
-(cherry picked from commit f05766469efc2a055085c0bcf9d40c4cdf47fe36)
----
- src/include/k5-buf.h                          |  8 ++++++
- src/util/support/k5buf.c                      | 26 +++++++++++--------
- src/util/support/libkrb5support-fixed.exports |  1 +
- 3 files changed, 24 insertions(+), 11 deletions(-)
-
-diff --git a/src/include/k5-buf.h b/src/include/k5-buf.h
-index f3207bd09..1223916a6 100644
---- a/src/include/k5-buf.h
-+++ b/src/include/k5-buf.h
-@@ -76,6 +76,14 @@ void k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...)
- #endif
-     ;
- 
-+/* Add sprintf-style formatted data to BUF, with a va_list.  The value of ap is
-+ * undefined after the call. */
-+void k5_buf_add_vfmt(struct k5buf *buf, const char *fmt, va_list ap)
-+#if !defined(__cplusplus) && (__GNUC__ > 2)
-+    __attribute__((__format__(__printf__, 2, 0)))
-+#endif
-+    ;
-+
- /* Extend the length of buf by len and return a pointer to the reserved space,
-  * to be filled in by the caller.  Return NULL on error. */
- void *k5_buf_get_space(struct k5buf *buf, size_t len);
-diff --git a/src/util/support/k5buf.c b/src/util/support/k5buf.c
-index f619f6a48..35978f238 100644
---- a/src/util/support/k5buf.c
-+++ b/src/util/support/k5buf.c
-@@ -141,9 +141,9 @@ k5_buf_add_len(struct k5buf *buf, const void *data, size_t len)
- }
- 
- void
--k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...)
-+k5_buf_add_vfmt(struct k5buf *buf, const char *fmt, va_list ap)
- {
--    va_list ap;
-+    va_list apcopy;
-     int r;
-     size_t remaining;
-     char *tmp;
-@@ -154,9 +154,7 @@ k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...)
- 
-     if (buf->buftype == K5BUF_FIXED) {
-         /* Format the data directly into the fixed buffer. */
--        va_start(ap, fmt);
-         r = vsnprintf(endptr(buf), remaining, fmt, ap);
--        va_end(ap);
-         if (SNPRINTF_OVERFLOW(r, remaining))
-             set_error(buf);
-         else
-@@ -166,9 +164,9 @@ k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...)
- 
-     /* Optimistically format the data directly into the dynamic buffer. */
-     assert(buf->buftype == K5BUF_DYNAMIC);
--    va_start(ap, fmt);
--    r = vsnprintf(endptr(buf), remaining, fmt, ap);
--    va_end(ap);
-+    va_copy(apcopy, ap);
-+    r = vsnprintf(endptr(buf), remaining, fmt, apcopy);
-+    va_end(apcopy);
-     if (!SNPRINTF_OVERFLOW(r, remaining)) {
-         buf->len += (unsigned int) r;
-         return;
-@@ -179,9 +177,7 @@ k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...)
-         if (!ensure_space(buf, r))
-             return;
-         remaining = buf->space - buf->len;
--        va_start(ap, fmt);
-         r = vsnprintf(endptr(buf), remaining, fmt, ap);
--        va_end(ap);
-         if (SNPRINTF_OVERFLOW(r, remaining))  /* Shouldn't ever happen. */
-             k5_buf_free(buf);
-         else
-@@ -191,9 +187,7 @@ k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...)
- 
-     /* It's a pre-C99 snprintf implementation, or something else went wrong.
-      * Fall back to asprintf. */
--    va_start(ap, fmt);
-     r = vasprintf(&tmp, fmt, ap);
--    va_end(ap);
-     if (r < 0) {
-         k5_buf_free(buf);
-         return;
-@@ -206,6 +200,16 @@ k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...)
-     free(tmp);
- }
- 
-+void
-+k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...)
-+{
-+    va_list ap;
-+
-+    va_start(ap, fmt);
-+    k5_buf_add_vfmt(buf, fmt, ap);
-+    va_end(ap);
-+}
-+
- void *
- k5_buf_get_space(struct k5buf *buf, size_t len)
- {
-diff --git a/src/util/support/libkrb5support-fixed.exports b/src/util/support/libkrb5support-fixed.exports
-index 30c946e7e..cb9bf0826 100644
---- a/src/util/support/libkrb5support-fixed.exports
-+++ b/src/util/support/libkrb5support-fixed.exports
-@@ -6,6 +6,7 @@ k5_buf_init_dynamic
- k5_buf_add
- k5_buf_add_len
- k5_buf_add_fmt
-+k5_buf_add_vfmt
- k5_buf_get_space
- k5_buf_truncate
- k5_buf_status
diff --git a/SOURCES/Add-k5_dir_filenames-to-libkrb5support.patch b/SOURCES/Add-k5_dir_filenames-to-libkrb5support.patch
deleted file mode 100644
index d420f15..0000000
--- a/SOURCES/Add-k5_dir_filenames-to-libkrb5support.patch
+++ /dev/null
@@ -1,222 +0,0 @@
-From 9010a0dbf59771cb0a9c1e6fd5a18a92a1200ca7 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Tue, 5 Jun 2018 14:01:05 -0400
-Subject: [PATCH] Add k5_dir_filenames() to libkrb5support
-
-Add a support function to get a list of filenames from a directory in
-sorted order.
-
-(cherry picked from commit 27534121eb39089ff4335d8b465027e9ba783682)
----
- src/include/k5-platform.h                     |   7 +
- src/util/support/Makefile.in                  |   3 +
- src/util/support/dir_filenames.c              | 135 ++++++++++++++++++
- src/util/support/libkrb5support-fixed.exports |   2 +
- 4 files changed, 147 insertions(+)
- create mode 100644 src/util/support/dir_filenames.c
-
-diff --git a/src/include/k5-platform.h b/src/include/k5-platform.h
-index 07ef6a4ca..763408a09 100644
---- a/src/include/k5-platform.h
-+++ b/src/include/k5-platform.h
-@@ -44,6 +44,8 @@
-  * + constant time memory comparison
-  * + path manipulation
-  * + _, N_, dgettext, bindtextdomain (for localization)
-+ * + getopt_long
-+ * + fetching filenames from a directory
-  */
- 
- #ifndef K5_PLATFORM_H
-@@ -1148,4 +1150,9 @@ extern int k5_getopt_long(int nargc, char **nargv, char *options,
- #define getopt_long k5_getopt_long
- #endif /* HAVE_GETOPT_LONG */
- 
-+/* Set *fnames_out to a null-terminated list of filenames within dirname,
-+ * sorted according to strcmp().  Return 0 on success, or ENOENT/ENOMEM. */
-+int k5_dir_filenames(const char *dirname, char ***fnames_out);
-+void k5_free_filenames(char **fnames);
-+
- #endif /* K5_PLATFORM_H */
-diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in
-index caaf15822..4715e0391 100644
---- a/src/util/support/Makefile.in
-+++ b/src/util/support/Makefile.in
-@@ -85,6 +85,7 @@ STLIBOBJS= \
- 	hex.o \
- 	bcmp.o \
- 	strerror_r.o \
-+	dir_filenames.o \
- 	$(GETTIMEOFDAY_ST_OBJ) \
- 	$(IPC_ST_OBJ) \
- 	$(STRLCPY_ST_OBJ) \
-@@ -111,6 +112,7 @@ LIBOBJS= \
- 	$(OUTPRE)hex.$(OBJEXT) \
- 	$(OUTPRE)bcmp.$(OBJEXT) \
- 	$(OUTPRE)strerror_r.$(OBJEXT) \
-+	$(OUTPRE)dir_filenames.$(OBJEXT) \
- 	$(GETTIMEOFDAY_OBJ) \
- 	$(IPC_OBJ) \
- 	$(STRLCPY_OBJ) \
-@@ -147,6 +149,7 @@ SRCS=\
- 	$(srcdir)/hex.c \
- 	$(srcdir)/bcmp.c \
- 	$(srcdir)/strerror_r.c \
-+	$(srcdir)/dir_filenames.c \
- 	$(srcdir)/t_utf8.c \
- 	$(srcdir)/t_utf16.c \
- 	$(srcdir)/getopt.c \
-diff --git a/src/util/support/dir_filenames.c b/src/util/support/dir_filenames.c
-new file mode 100644
-index 000000000..9312b0238
---- /dev/null
-+++ b/src/util/support/dir_filenames.c
-@@ -0,0 +1,135 @@
-+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-+/* util/support/dir_filenames.c - fetch filenames in a directory */
-+/*
-+ * Copyright (C) 2018 by the Massachusetts Institute of Technology.
-+ * 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.
-+ *
-+ * 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 HOLDER 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 "k5-platform.h"
-+
-+void
-+k5_free_filenames(char **fnames)
-+{
-+    char **fn;
-+
-+    for (fn = fnames; fn != NULL && *fn != NULL; fn++)
-+        free(*fn);
-+    free(fnames);
-+}
-+
-+/* Resize the filename list and add a name. */
-+static int
-+add_filename(char ***fnames, int *n_fnames, const char *name)
-+{
-+    char **newlist;
-+
-+    newlist = realloc(*fnames, (*n_fnames + 2) * sizeof(*newlist));
-+    if (newlist == NULL)
-+        return ENOMEM;
-+    *fnames = newlist;
-+    newlist[*n_fnames] = strdup(name);
-+    if (newlist[*n_fnames] == NULL)
-+        return ENOMEM;
-+    (*n_fnames)++;
-+    newlist[*n_fnames] = NULL;
-+    return 0;
-+}
-+
-+static int
-+compare_with_strcmp(const void *a, const void *b)
-+{
-+    return strcmp(*(char **)a, *(char **)b);
-+}
-+
-+#ifdef _WIN32
-+
-+int
-+k5_dir_filenames(const char *dirname, char ***fnames_out)
-+{
-+    char *wildcard;
-+    WIN32_FIND_DATA ffd;
-+    HANDLE handle;
-+    char **fnames = NULL;
-+    int n_fnames = 0;
-+
-+    *fnames_out = NULL;
-+
-+    if (asprintf(&wildcard, "%s\\*", dirname) < 0)
-+        return ENOMEM;
-+    handle = FindFirstFile(wildcard, &ffd);
-+    free(wildcard);
-+    if (handle == INVALID_HANDLE_VALUE)
-+        return ENOENT;
-+
-+    do {
-+        if (add_filename(&fnames, &n_fnames, &ffd.cFileName) != 0) {
-+            k5_free_filenames(fnames);
-+            FindClose(handle);
-+            return ENOMEM;
-+        }
-+    } while (FindNextFile(handle, &ffd) != 0);
-+
-+    FindClose(handle);
-+    qsort(fnames, n_fnames, sizeof(*fnames), compare_with_strcmp);
-+    *fnames_out = fnames;
-+    return 0;
-+}
-+
-+#else /* _WIN32 */
-+
-+#include <dirent.h>
-+
-+int
-+k5_dir_filenames(const char *dirname, char ***fnames_out)
-+{
-+    DIR *dir;
-+    struct dirent *ent;
-+    char **fnames = NULL;
-+    int n_fnames = 0;
-+
-+    *fnames_out = NULL;
-+
-+    dir = opendir(dirname);
-+    if (dir == NULL)
-+        return ENOENT;
-+
-+    while ((ent = readdir(dir)) != NULL) {
-+        if (add_filename(&fnames, &n_fnames, ent->d_name) != 0) {
-+            k5_free_filenames(fnames);
-+            closedir(dir);
-+            return ENOMEM;
-+        }
-+    }
-+
-+    closedir(dir);
-+    qsort(fnames, n_fnames, sizeof(*fnames), compare_with_strcmp);
-+    *fnames_out = fnames;
-+    return 0;
-+}
-+
-+#endif /* not _WIN32 */
-diff --git a/src/util/support/libkrb5support-fixed.exports b/src/util/support/libkrb5support-fixed.exports
-index a5e2ade04..16ed5a6c1 100644
---- a/src/util/support/libkrb5support-fixed.exports
-+++ b/src/util/support/libkrb5support-fixed.exports
-@@ -58,6 +58,8 @@ k5_path_split
- k5_strerror_r
- k5_utf8_to_utf16le
- k5_utf16le_to_utf8
-+k5_dir_filenames
-+k5_free_filenames
- krb5int_key_register
- krb5int_key_delete
- krb5int_getspecific
diff --git a/SOURCES/Add-k5test-mark-function.patch b/SOURCES/Add-k5test-mark-function.patch
deleted file mode 100644
index 0b2b9fa..0000000
--- a/SOURCES/Add-k5test-mark-function.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From 68b61c6d6402c0ad57509705137c92ae814ace27 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Wed, 18 Apr 2018 19:21:40 -0400
-Subject: [PATCH] Add k5test mark() function
-
-Make it easier to locate a failing command in long Python test scripts
-by allowing the script to output marks, and displaying the most recent
-mark with command failures.
-
-(cherry picked from commit 4e813204ac3dace93297f47d64dfc0aaecc370f8)
----
- src/util/k5test.py | 14 ++++++++++++++
- 1 file changed, 14 insertions(+)
-
-diff --git a/src/util/k5test.py b/src/util/k5test.py
-index 4d30baf40..bc32877a7 100644
---- a/src/util/k5test.py
-+++ b/src/util/k5test.py
-@@ -141,6 +141,11 @@ Scripts may use the following functions and variables:
-   added newline) in testlog, and write it to stdout if running
-   verbosely.
- 
-+* mark(message): Place a divider message in the test output, to make
-+  it easier to determine what part of the test script a command
-+  invocation belongs to.  The last mark message will also be displayed
-+  if a command invocation fails.  Do not include a newline in message.
-+
- * which(progname): Return the location of progname in the executable
-   path, or None if it is not found.
- 
-@@ -376,6 +381,8 @@ def fail(msg):
-     """Print a message and exit with failure."""
-     global _current_pass
-     print "*** Failure:", msg
-+    if _last_mark:
-+        print "*** Last mark: %s" % _last_mark
-     if _last_cmd:
-         print "*** Last command (#%d): %s" % (_cmd_index - 1, _last_cmd)
-     if _last_cmd_output:
-@@ -392,6 +399,12 @@ def success(msg):
-     _success = True
- 
- 
-+def mark(msg):
-+    global _last_mark
-+    output('\n====== %s ======\n' % msg)
-+    _last_mark = msg
-+
-+
- def skipped(whatmsg, whymsg):
-     output('*** Skipping: %s: %s\n' % (whatmsg, whymsg), force_verbose=True)
-     f = open(os.path.join(buildtop, 'skiptests'), 'a')
-@@ -1275,6 +1288,7 @@ atexit.register(_onexit)
- signal.signal(signal.SIGINT, _onsigint)
- _outfile = open('testlog', 'w')
- _cmd_index = 1
-+_last_mark = None
- _last_cmd = None
- _last_cmd_output = None
- buildtop = _find_buildtop()
diff --git a/SOURCES/Add-libkrb5support-hex-functions-and-tests.patch b/SOURCES/Add-libkrb5support-hex-functions-and-tests.patch
deleted file mode 100644
index d7caab2..0000000
--- a/SOURCES/Add-libkrb5support-hex-functions-and-tests.patch
+++ /dev/null
@@ -1,484 +0,0 @@
-From 507b1aff60fdadc91ca7c56d39711049aeeb1e58 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Mon, 19 Feb 2018 00:51:44 -0500
-Subject: [PATCH] Add libkrb5support hex functions and tests
-
-(cherry picked from commit 720dea558da0062d3cea4385327161e62cf09a5e)
-[rharwood@redhat.com Remove .gitignore]
----
- src/include/k5-hex.h                          |  53 ++++++
- src/util/support/Makefile.in                  |  15 +-
- src/util/support/deps                         |   6 +
- src/util/support/hex.c                        | 116 ++++++++++++
- src/util/support/libkrb5support-fixed.exports |   2 +
- src/util/support/t_hex.c                      | 169 ++++++++++++++++++
- 6 files changed, 358 insertions(+), 3 deletions(-)
- create mode 100644 src/include/k5-hex.h
- create mode 100644 src/util/support/hex.c
- create mode 100644 src/util/support/t_hex.c
-
-diff --git a/src/include/k5-hex.h b/src/include/k5-hex.h
-new file mode 100644
-index 000000000..75bd2cb19
---- /dev/null
-+++ b/src/include/k5-hex.h
-@@ -0,0 +1,53 @@
-+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-+/* include/k5-hex.h - libkrb5support hex encoding/decoding declarations */
-+/*
-+ * Copyright (C) 2018 by the Massachusetts Institute of Technology.
-+ * 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.
-+ *
-+ * 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 HOLDER 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.
-+ */
-+
-+#ifndef K5_HEX_H
-+#define K5_HEX_H
-+
-+#include "k5-platform.h"
-+
-+/*
-+ * Encode len bytes in hex, placing the result in allocated storage in
-+ * *hex_out.  Use uppercase hex digits if uppercase is non-zero.  Return 0 on
-+ * success, ENOMEM on error.
-+ */
-+int k5_hex_encode(const void *bytes, size_t len, int uppercase,
-+                  char **hex_out);
-+
-+/*
-+ * Decode hex bytes, placing the result in allocated storage in *bytes_out and
-+ * *len_out.  Null-terminate the result (primarily for decoding passwords in
-+ * libkdb_ldap).  Return 0 on success, ENOMEM or EINVAL on error.
-+ */
-+int k5_hex_decode(const char *hex, uint8_t **bytes_out, size_t *len_out);
-+
-+#endif /* K5_HEX_H */
-diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in
-index 58ac2e333..caaf15822 100644
---- a/src/util/support/Makefile.in
-+++ b/src/util/support/Makefile.in
-@@ -82,6 +82,7 @@ STLIBOBJS= \
- 	path.o \
- 	base64.o \
- 	json.o \
-+	hex.o \
- 	bcmp.o \
- 	strerror_r.o \
- 	$(GETTIMEOFDAY_ST_OBJ) \
-@@ -107,6 +108,7 @@ LIBOBJS= \
- 	$(OUTPRE)path.$(OBJEXT) \
- 	$(OUTPRE)base64.$(OBJEXT) \
- 	$(OUTPRE)json.$(OBJEXT) \
-+	$(OUTPRE)hex.$(OBJEXT) \
- 	$(OUTPRE)bcmp.$(OBJEXT) \
- 	$(OUTPRE)strerror_r.$(OBJEXT) \
- 	$(GETTIMEOFDAY_OBJ) \
-@@ -137,10 +139,12 @@ SRCS=\
- 	$(srcdir)/t_unal.c \
- 	$(srcdir)/t_path.c \
- 	$(srcdir)/t_json.c \
-+	$(srcdir)/t_hex.c \
- 	$(srcdir)/zap.c \
- 	$(srcdir)/path.c \
- 	$(srcdir)/base64.c \
- 	$(srcdir)/json.c \
-+	$(srcdir)/hex.c \
- 	$(srcdir)/bcmp.c \
- 	$(srcdir)/strerror_r.c \
- 	$(srcdir)/t_utf8.c \
-@@ -216,6 +220,9 @@ T_JSON_OBJS= t_json.o json.o base64.o k5buf.o $(PRINTF_ST_OBJ)
- t_json: $(T_JSON_OBJS)
- 	$(CC_LINK) -o $@ $(T_JSON_OBJS)
- 
-+t_hex: t_hex.o hex.o
-+	$(CC_LINK) -o $@ t_hex.o hex.o
-+
- t_unal: t_unal.o
- 	$(CC_LINK) -o t_unal t_unal.o
- 
-@@ -227,7 +234,8 @@ T_UTF16_OBJS= t_utf16.o utf8_conv.o utf8.o k5buf.o $(PRINTF_ST_OBJ)
- t_utf16: $(T_UTF16_OBJS)
- 	$(CC_LINK) -o $@ $(T_UTF16_OBJS)
- 
--TEST_PROGS= t_k5buf t_path t_path_win t_base64 t_json t_unal t_utf8 t_utf16
-+TEST_PROGS= t_k5buf t_path t_path_win t_base64 t_json t_hex t_unal t_utf8 \
-+	t_utf16
- 
- check-unix: $(TEST_PROGS)
- 	./t_k5buf
-@@ -235,6 +243,7 @@ check-unix: $(TEST_PROGS)
- 	./t_path_win
- 	./t_base64
- 	./t_json
-+	./t_hex
- 	./t_unal
- 	./t_utf8
- 	./t_utf16
-@@ -242,8 +251,8 @@ check-unix: $(TEST_PROGS)
- clean:
- 	$(RM) t_k5buf.o t_k5buf t_unal.o t_unal path_win.o path_win
- 	$(RM) t_path_win.o t_path_win t_path.o t_path t_base64.o t_base64
--	$(RM) t_json.o t_json libkrb5support.exports t_utf8.o t_utf8
--	$(RM) t_utf16.o t_utf16
-+	$(RM) t_json.o t_json t_hex.o t_hex libkrb5support.exports
-+	$(RM) t_utf8.o t_utf8 t_utf16.o t_utf16
- 
- @lib_frag@
- @libobj_frag@
-diff --git a/src/util/support/deps b/src/util/support/deps
-index 34d8a884b..80e9a1c58 100644
---- a/src/util/support/deps
-+++ b/src/util/support/deps
-@@ -63,6 +63,9 @@ t_path.so t_path.po $(OUTPRE)t_path.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-   t_path.c
- t_json.so t_json.po $(OUTPRE)t_json.$(OBJEXT): $(top_srcdir)/include/k5-json.h \
-   t_json.c
-+t_hex.so t_hex.po $(OUTPRE)t_hex.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-+  $(top_srcdir)/include/k5-hex.h $(top_srcdir)/include/k5-platform.h \
-+  $(top_srcdir)/include/k5-thread.h t_hex.c
- zap.so zap.po $(OUTPRE)zap.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-   $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \
-   zap.c
-@@ -76,6 +79,9 @@ json.so json.po $(OUTPRE)json.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-   $(top_srcdir)/include/k5-base64.h $(top_srcdir)/include/k5-buf.h \
-   $(top_srcdir)/include/k5-json.h $(top_srcdir)/include/k5-platform.h \
-   $(top_srcdir)/include/k5-thread.h json.c
-+hex.so hex.po $(OUTPRE)hex.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-+  $(top_srcdir)/include/k5-hex.h $(top_srcdir)/include/k5-platform.h \
-+  $(top_srcdir)/include/k5-thread.h hex.c
- bcmp.so bcmp.po $(OUTPRE)bcmp.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-   $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \
-   bcmp.c
-diff --git a/src/util/support/hex.c b/src/util/support/hex.c
-new file mode 100644
-index 000000000..4407ff9ff
---- /dev/null
-+++ b/src/util/support/hex.c
-@@ -0,0 +1,116 @@
-+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-+/* util/support/hex.c - hex encoding/decoding implementation */
-+/*
-+ * Copyright (C) 2018 by the Massachusetts Institute of Technology.
-+ * 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.
-+ *
-+ * 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 HOLDER 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 <k5-platform.h>
-+#include <k5-hex.h>
-+#include <ctype.h>
-+
-+static inline char
-+hex_digit(uint8_t bval, int uppercase)
-+{
-+    assert(bval >= 0 && bval <= 0xF);
-+    if (bval < 10)
-+        return '0' + bval;
-+    else if (uppercase)
-+        return 'A' + (bval - 10);
-+    else
-+        return 'a' + (bval - 10);
-+}
-+
-+int
-+k5_hex_encode(const void *bytes, size_t len, int uppercase, char **hex_out)
-+{
-+    size_t i;
-+    const uint8_t *p = bytes;
-+    char *hex;
-+
-+    *hex_out = NULL;
-+
-+    hex = malloc(len * 2 + 1);
-+    if (hex == NULL)
-+        return ENOMEM;
-+
-+    for (i = 0; i < len; i++) {
-+        hex[i * 2] = hex_digit(p[i] >> 4, uppercase);
-+        hex[i * 2 + 1] = hex_digit(p[i] & 0xF, uppercase);
-+    }
-+    hex[len * 2] = '\0';
-+
-+    *hex_out = hex;
-+    return 0;
-+}
-+
-+/* Decode a hex digit.  Return 0-15 on success, -1 on invalid input. */
-+static inline int
-+decode_hexchar(unsigned char c)
-+{
-+    if (isdigit(c))
-+        return c - '0';
-+    if (c >= 'A' && c <= 'F')
-+        return c - 'A' + 10;
-+    if (c >= 'a' && c <= 'f')
-+        return c - 'a' + 10;
-+    return -1;
-+}
-+
-+int
-+k5_hex_decode(const char *hex, uint8_t **bytes_out, size_t *len_out)
-+{
-+    size_t hexlen, i;
-+    int h1, h2;
-+    uint8_t *bytes;
-+
-+    *bytes_out = NULL;
-+    *len_out = 0;
-+
-+    hexlen = strlen(hex);
-+    if (hexlen % 2 != 0)
-+        return EINVAL;
-+    bytes = malloc(hexlen / 2 + 1);
-+    if (bytes == NULL)
-+        return ENOMEM;
-+
-+    for (i = 0; i < hexlen / 2; i++) {
-+        h1 = decode_hexchar(hex[i * 2]);
-+        h2 = decode_hexchar(hex[i * 2 + 1]);
-+        if (h1 == -1 || h2 == -1) {
-+            free(bytes);
-+            return EINVAL;
-+        }
-+        bytes[i] = h1 * 16 + h2;
-+    }
-+    bytes[i] = 0;
-+
-+    *bytes_out = bytes;
-+    *len_out = hexlen / 2;
-+    return 0;
-+}
-diff --git a/src/util/support/libkrb5support-fixed.exports b/src/util/support/libkrb5support-fixed.exports
-index fd74a1897..30c946e7e 100644
---- a/src/util/support/libkrb5support-fixed.exports
-+++ b/src/util/support/libkrb5support-fixed.exports
-@@ -16,6 +16,8 @@ k5_get_error
- k5_free_error
- k5_clear_error
- k5_set_error_info_callout_fn
-+k5_hex_decode
-+k5_hex_encode
- k5_json_array_add
- k5_json_array_create
- k5_json_array_fmt
-diff --git a/src/util/support/t_hex.c b/src/util/support/t_hex.c
-new file mode 100644
-index 000000000..a586a1bc8
---- /dev/null
-+++ b/src/util/support/t_hex.c
-@@ -0,0 +1,169 @@
-+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-+/* util/support/t_hex.c - Test hex encoding and decoding */
-+/*
-+ * Copyright (C) 2018 by the Massachusetts Institute of Technology.
-+ * 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.
-+ *
-+ * 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 HOLDER 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 <k5-platform.h>
-+#include <k5-hex.h>
-+
-+struct {
-+    const char *hex;
-+    const char *binary;
-+    size_t binary_len;
-+    int uppercase;
-+} tests[] = {
-+    /* Invalid hex strings */
-+    { "1" },
-+    { "123" },
-+    { "0/" },
-+    { "/0" },
-+    { "0:" },
-+    { ":0" },
-+    { "0@" },
-+    { "@0" },
-+    { "0G" },
-+    { "G0" },
-+    { "0`" },
-+    { "`0" },
-+    { "0g" },
-+    { "g0" },
-+    { " 00 " },
-+    { "0\x01" },
-+
-+    { "", "", 0 },
-+    { "00", "\x00", 1 },
-+    { "01", "\x01", 1 },
-+    { "10", "\x10", 1 },
-+    { "01ff", "\x01\xFF", 2 },
-+    { "A0B0C0", "\xA0\xB0\xC0", 3, 1 },
-+    { "1a2b3c4d5e6f", "\x1A\x2B\x3C\x4D\x5E\x6F", 6 },
-+    { "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
-+      "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
-+      "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 32 },
-+
-+    /* All byte values, lowercase */
-+    { "0001020304050607", "\x00\x01\x02\x03\x04\x05\x06\x07", 8 },
-+    { "08090a0b0c0d0e0f", "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 8 },
-+    { "1011121314151617", "\x10\x11\x12\x13\x14\x15\x16\x17", 8 },
-+    { "18191a1b1c1d1e1f", "\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", 8 },
-+    { "2021222324252627", "\x20\x21\x22\x23\x24\x25\x26\x27", 8 },
-+    { "28292a2b2c2d2e2f", "\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F", 8 },
-+    { "3031323334353637", "\x30\x31\x32\x33\x34\x35\x36\x37", 8 },
-+    { "38393a3b3c3d3e3f", "\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F", 8 },
-+    { "4041424344454647", "\x40\x41\x42\x43\x44\x45\x46\x47", 8 },
-+    { "48494a4b4c4d4e4f", "\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F", 8 },
-+    { "5051525354555657", "\x50\x51\x52\x53\x54\x55\x56\x57", 8 },
-+    { "58595a5b5c5d5e5f", "\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F", 8 },
-+    { "6061626364656667", "\x60\x61\x62\x63\x64\x65\x66\x67", 8 },
-+    { "68696a6b6c6d6e6f", "\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F", 8 },
-+    { "7071727374757677", "\x70\x71\x72\x73\x74\x75\x76\x77", 8 },
-+    { "78797a7b7c7d7e7f", "\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F", 8 },
-+    { "8081828384858687", "\x80\x81\x82\x83\x84\x85\x86\x87", 8 },
-+    { "88898a8b8c8d8e8f", "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F", 8 },
-+    { "9091929394959697", "\x90\x91\x92\x93\x94\x95\x96\x97", 8 },
-+    { "98999a9b9c9d9e9f", "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F", 8 },
-+    { "a0a1a2a3a4a5a6a7", "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7", 8 },
-+    { "a8a9aaabacadaeaf", "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF", 8 },
-+    { "b0b1b2b3b4b5b6b7", "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7", 8 },
-+    { "b8b9babbbcbdbebf", "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF", 8 },
-+    { "c0c1c2c3c4c5c6c7", "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7", 8 },
-+    { "c8c9cacbcccdcecf", "\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF", 8 },
-+    { "d0d1d2d3d4d5d6d7", "\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7", 8 },
-+    { "d8d9dadbdcdddedf", "\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF", 8 },
-+    { "e0e1e2e3e4e5e6e7", "\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7", 8 },
-+    { "e8e9eaebecedeeef", "\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF", 8 },
-+    { "f0f1f2f3f4f5f6f7", "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7", 8 },
-+    { "f8f9fafbfcfdfeff", "\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF", 8 },
-+
-+    /* All byte values, uppercase */
-+    { "0001020304050607", "\x00\x01\x02\x03\x04\x05\x06\x07", 8, 1 },
-+    { "08090A0B0C0D0E0F", "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 8, 1 },
-+    { "1011121314151617", "\x10\x11\x12\x13\x14\x15\x16\x17", 8, 1 },
-+    { "18191A1B1C1D1E1F", "\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", 8, 1 },
-+    { "2021222324252627", "\x20\x21\x22\x23\x24\x25\x26\x27", 8, 1 },
-+    { "28292A2B2C2D2E2F", "\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F", 8, 1 },
-+    { "3031323334353637", "\x30\x31\x32\x33\x34\x35\x36\x37", 8, 1 },
-+    { "38393A3B3C3D3E3F", "\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F", 8, 1 },
-+    { "4041424344454647", "\x40\x41\x42\x43\x44\x45\x46\x47", 8, 1 },
-+    { "48494A4B4C4D4E4F", "\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F", 8, 1 },
-+    { "5051525354555657", "\x50\x51\x52\x53\x54\x55\x56\x57", 8, 1 },
-+    { "58595A5B5C5D5E5F", "\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F", 8, 1 },
-+    { "6061626364656667", "\x60\x61\x62\x63\x64\x65\x66\x67", 8, 1 },
-+    { "68696A6B6C6D6E6F", "\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F", 8, 1 },
-+    { "7071727374757677", "\x70\x71\x72\x73\x74\x75\x76\x77", 8, 1 },
-+    { "78797A7B7C7D7E7F", "\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F", 8, 1 },
-+    { "8081828384858687", "\x80\x81\x82\x83\x84\x85\x86\x87", 8, 1 },
-+    { "88898A8B8C8D8E8F", "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F", 8, 1 },
-+    { "9091929394959697", "\x90\x91\x92\x93\x94\x95\x96\x97", 8, 1 },
-+    { "98999A9B9C9D9E9F", "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F", 8, 1 },
-+    { "A0A1A2A3A4A5A6A7", "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7", 8, 1 },
-+    { "A8A9AAABACADAEAF", "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF", 8, 1 },
-+    { "B0B1B2B3B4B5B6B7", "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7", 8, 1 },
-+    { "B8B9BABBBCBDBEBF", "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF", 8, 1 },
-+    { "C0C1C2C3C4C5C6C7", "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7", 8, 1 },
-+    { "C8C9CACBCCCDCECF", "\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF", 8, 1 },
-+    { "D0D1D2D3D4D5D6D7", "\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7", 8, 1 },
-+    { "D8D9DADBDCDDDEDF", "\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF", 8, 1 },
-+    { "E0E1E2E3E4E5E6E7", "\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7", 8, 1 },
-+    { "E8E9EAEBECEDEEEF", "\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF", 8, 1 },
-+    { "F0F1F2F3F4F5F6F7", "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7", 8, 1 },
-+    { "F8F9FAFBFCFDFEFF", "\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF", 8, 1 },
-+};
-+
-+int main()
-+{
-+    size_t i;
-+    char *hex;
-+    int ret;
-+    uint8_t *bytes;
-+    size_t len;
-+
-+    for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
-+        if (tests[i].binary == NULL) {
-+            ret = k5_hex_decode(tests[i].hex, &bytes, &len);
-+            assert(ret == EINVAL && bytes == NULL && len == 0);
-+            continue;
-+        }
-+
-+        ret = k5_hex_decode(tests[i].hex, &bytes, &len);
-+        assert(ret == 0);
-+        assert(len == tests[i].binary_len);
-+        assert(memcmp(bytes, tests[i].binary, len) == 0);
-+        assert(bytes[len] == 0);
-+        free(bytes);
-+
-+        ret = k5_hex_encode((uint8_t *)tests[i].binary, tests[i].binary_len,
-+                            tests[i].uppercase, &hex);
-+        assert(ret == 0);
-+        assert(strcmp(tests[i].hex, hex) == 0);
-+        free(hex);
-+    }
-+    return 0;
-+}
diff --git a/SOURCES/Add-tests-for-KCM-ccache-type.patch b/SOURCES/Add-tests-for-KCM-ccache-type.patch
new file mode 100644
index 0000000..8aa8f23
--- /dev/null
+++ b/SOURCES/Add-tests-for-KCM-ccache-type.patch
@@ -0,0 +1,295 @@
+From dd863eb4311310c23ee12961fa8e91703f29a6f5 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/Add-vector-support-to-k5_sha256.patch b/SOURCES/Add-vector-support-to-k5_sha256.patch
deleted file mode 100644
index f9a3233..0000000
--- a/SOURCES/Add-vector-support-to-k5_sha256.patch
+++ /dev/null
@@ -1,106 +0,0 @@
-From f8b14b92cc4c82578f8fc56dd1fddebe88120769 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Sat, 3 Feb 2018 20:53:42 -0500
-Subject: [PATCH] Add vector support to k5_sha256()
-
-Add a length argument so that multiple krb5_data values can be passed
-to k5_sha256(), for efficient computation of SHA-256 hashes over
-concatenations of data values.
-
-(cherry picked from commit 4f3373e8c55b3e9bdfb5b065e07214c5816c85fa)
----
- src/include/k5-int.h                 | 4 ++--
- src/lib/crypto/builtin/sha2/sha256.c | 6 ++++--
- src/lib/crypto/crypto_tests/t_sha2.c | 2 +-
- src/lib/crypto/openssl/sha256.c      | 6 ++++--
- src/lib/krb5/rcache/rc_conv.c        | 2 +-
- 5 files changed, 12 insertions(+), 8 deletions(-)
-
-diff --git a/src/include/k5-int.h b/src/include/k5-int.h
-index 9378ae047..1c1d9783b 100644
---- a/src/include/k5-int.h
-+++ b/src/include/k5-int.h
-@@ -635,9 +635,9 @@ krb5int_arcfour_gsscrypt(const krb5_keyblock *keyblock, krb5_keyusage usage,
- 
- #define K5_SHA256_HASHLEN (256 / 8)
- 
--/* Write the SHA-256 hash of in to out. */
-+/* Write the SHA-256 hash of in (containing n elements) to out. */
- krb5_error_code
--k5_sha256(const krb5_data *in, uint8_t out[K5_SHA256_HASHLEN]);
-+k5_sha256(const krb5_data *in, size_t n, uint8_t out[K5_SHA256_HASHLEN]);
- 
- /*
-  * Attempt to zero memory in a way that compilers won't optimize out.
-diff --git a/src/lib/crypto/builtin/sha2/sha256.c b/src/lib/crypto/builtin/sha2/sha256.c
-index 2b5cbe480..9a940b3f8 100644
---- a/src/lib/crypto/builtin/sha2/sha256.c
-+++ b/src/lib/crypto/builtin/sha2/sha256.c
-@@ -257,12 +257,14 @@ k5_sha256_final(void *res, SHA256_CTX *m)
- }
- 
- krb5_error_code
--k5_sha256(const krb5_data *in, uint8_t out[K5_SHA256_HASHLEN])
-+k5_sha256(const krb5_data *in, size_t n, uint8_t out[K5_SHA256_HASHLEN])
- {
-     SHA256_CTX ctx;
-+    size_t i;
- 
-     k5_sha256_init(&ctx);
--    k5_sha256_update(&ctx, in->data, in->length);
-+    for (i = 0; i < n; i++)
-+        k5_sha256_update(&ctx, in[i].data, in[i].length);
-     k5_sha256_final(out, &ctx);
-     return 0;
- }
-diff --git a/src/lib/crypto/crypto_tests/t_sha2.c b/src/lib/crypto/crypto_tests/t_sha2.c
-index 12f32869b..e6fa58498 100644
---- a/src/lib/crypto/crypto_tests/t_sha2.c
-+++ b/src/lib/crypto/crypto_tests/t_sha2.c
-@@ -125,7 +125,7 @@ hash_test(const struct krb5_hash_provider *hash, struct test *tests)
- 
- 	    if (hash == &krb5int_hash_sha256) {
- 		/* Try again using k5_sha256(). */
--		if (k5_sha256(&iov.data, (uint8_t *)hval.data) != 0)
-+		if (k5_sha256(&iov.data, 1, (uint8_t *)hval.data) != 0)
- 		    abort();
- 		if (memcmp(hval.data, t->hash, hval.length) != 0)
- 		    abort();
-diff --git a/src/lib/crypto/openssl/sha256.c b/src/lib/crypto/openssl/sha256.c
-index fa095d472..0edd8b7ba 100644
---- a/src/lib/crypto/openssl/sha256.c
-+++ b/src/lib/crypto/openssl/sha256.c
-@@ -34,16 +34,18 @@
- #include <openssl/evp.h>
- 
- krb5_error_code
--k5_sha256(const krb5_data *in, uint8_t out[K5_SHA256_HASHLEN])
-+k5_sha256(const krb5_data *in, size_t n, uint8_t out[K5_SHA256_HASHLEN])
- {
-     EVP_MD_CTX *ctx;
-+    size_t i;
-     int ok;
- 
-     ctx = EVP_MD_CTX_new();
-     if (ctx == NULL)
-         return ENOMEM;
-     ok = EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
--    ok = ok && EVP_DigestUpdate(ctx, in->data, in->length);
-+    for (i = 0; i < n; i++)
-+        ok = ok && EVP_DigestUpdate(ctx, in[i].data, in[i].length);
-     ok = ok && EVP_DigestFinal_ex(ctx, out, NULL);
-     EVP_MD_CTX_free(ctx);
-     return ok ? 0 : ENOMEM;
-diff --git a/src/lib/krb5/rcache/rc_conv.c b/src/lib/krb5/rcache/rc_conv.c
-index 0e021f5d8..f2fe528ac 100644
---- a/src/lib/krb5/rcache/rc_conv.c
-+++ b/src/lib/krb5/rcache/rc_conv.c
-@@ -58,7 +58,7 @@ krb5_rc_hash_message(krb5_context context, const krb5_data *message,
-     *out = NULL;
- 
-     /* Calculate the binary checksum. */
--    retval = k5_sha256(message, cksum);
-+    retval = k5_sha256(message, 1, cksum);
-     if (retval)
-         return retval;
- 
diff --git a/SOURCES/Address-some-optimized-out-memset-calls.patch b/SOURCES/Address-some-optimized-out-memset-calls.patch
new file mode 100644
index 0000000..58b1b25
--- /dev/null
+++ b/SOURCES/Address-some-optimized-out-memset-calls.patch
@@ -0,0 +1,95 @@
+From 54348bbfaec50bb72d1625c015f8e5c4cfa59e0d 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/Be-more-careful-asking-for-AS-key-in-SPAKE-client.patch b/SOURCES/Be-more-careful-asking-for-AS-key-in-SPAKE-client.patch
deleted file mode 100644
index 692f4ad..0000000
--- a/SOURCES/Be-more-careful-asking-for-AS-key-in-SPAKE-client.patch
+++ /dev/null
@@ -1,229 +0,0 @@
-From 2b9e79d58b28196dba5f7d3ff2f32ca577444ddc Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Sat, 31 Mar 2018 10:43:49 -0400
-Subject: [PATCH] Be more careful asking for AS key in SPAKE client
-
-Asking for the AS key too early can result in password prompts in
-situations where SPAKE won't proceed, such as when the KDC offers only
-second factor types not supported by the client.
-
-In spake_prep_questions(), decode the received message and make sure
-it's a challenge with a supported group and second factor type
-(SF-NONE at the moment).  Save the decoded message and use it in
-spake_process().  Do not retrieve the AS key at the beginning of
-spake_process(); instead do so in process_challenge() after checking
-the challenge group and factor types.
-
-Move contains_sf_none() earlier in the file so that it can be used by
-spake_prep_questions() without a prototype.
-
-ticket: 8659
-(cherry picked from commit f240f1b0d324312be8aa59ead7cfbe0c329ed064)
----
- src/plugins/preauth/spake/spake_client.c | 111 ++++++++++++++---------
- 1 file changed, 66 insertions(+), 45 deletions(-)
-
-diff --git a/src/plugins/preauth/spake/spake_client.c b/src/plugins/preauth/spake/spake_client.c
-index d72bd64aa..47a6ba26c 100644
---- a/src/plugins/preauth/spake/spake_client.c
-+++ b/src/plugins/preauth/spake/spake_client.c
-@@ -39,12 +39,26 @@
- #include <krb5/clpreauth_plugin.h>
- 
- typedef struct reqstate_st {
-+    krb5_pa_spake *msg;         /* set in prep_questions, used in process */
-     krb5_keyblock *initial_key;
-     krb5_data *support;
-     krb5_data thash;
-     krb5_data spakeresult;
- } reqstate;
- 
-+/* Return true if SF-NONE is present in factors. */
-+static krb5_boolean
-+contains_sf_none(krb5_spake_factor **factors)
-+{
-+    int i;
-+
-+    for (i = 0; factors != NULL && factors[i] != NULL; i++) {
-+        if (factors[i]->type == SPAKE_SF_NONE)
-+            return TRUE;
-+    }
-+    return FALSE;
-+}
-+
- static krb5_error_code
- spake_init(krb5_context context, krb5_clpreauth_moddata *moddata_out)
- {
-@@ -77,6 +91,7 @@ spake_request_fini(krb5_context context, krb5_clpreauth_moddata moddata,
- {
-     reqstate *st = (reqstate *)modreq;
- 
-+    k5_free_pa_spake(context, st->msg);
-     krb5_free_keyblock(context, st->initial_key);
-     krb5_free_data(context, st->support);
-     krb5_free_data_contents(context, &st->thash);
-@@ -92,16 +107,42 @@ spake_prep_questions(krb5_context context, krb5_clpreauth_moddata moddata,
-                      krb5_data *enc_req, krb5_data *enc_prev_req,
-                      krb5_pa_data *pa_data)
- {
-+    krb5_error_code ret;
-+    groupstate *gstate = (groupstate *)moddata;
-     reqstate *st = (reqstate *)modreq;
-+    krb5_data in_data;
-+    krb5_spake_challenge *ch;
- 
-     if (st == NULL)
-         return ENOMEM;
--    if (st->initial_key == NULL && pa_data->length > 0)
-+
-+    /* We don't need to ask any questions to send a support message. */
-+    if (pa_data->length == 0)
-+        return 0;
-+
-+    /* Decode the incoming message, replacing any previous one in the request
-+     * state.  If we can't decode it, we have no questions to ask. */
-+    k5_free_pa_spake(context, st->msg);
-+    st->msg = NULL;
-+    in_data = make_data(pa_data->contents, pa_data->length);
-+    ret = decode_krb5_pa_spake(&in_data, &st->msg);
-+    if (ret)
-+        return (ret == ENOMEM) ? ENOMEM : 0;
-+
-+    if (st->msg->choice == SPAKE_MSGTYPE_CHALLENGE) {
-+        ch = &st->msg->u.challenge;
-+        if (!group_is_permitted(gstate, ch->group))
-+            return 0;
-+        /* When second factor support is implemented, we should ask questions
-+         * based on the factors in the challenge. */
-+        if (!contains_sf_none(ch->factors))
-+            return 0;
-+        /* We will need the AS key to respond to the challenge. */
-         cb->need_as_key(context, rock);
--
--    /* When second-factor is implemented, we should ask questions based on the
--     * factors in the challenge. */
--
-+    } else if (st->msg->choice == SPAKE_MSGTYPE_ENCDATA) {
-+        /* When second factor support is implemented, we should decrypt the
-+         * encdata message and ask questions based on the factor data. */
-+    }
-     return 0;
- }
- 
-@@ -136,19 +177,6 @@ send_support(krb5_context context, groupstate *gstate, reqstate *st,
-     return convert_to_padata(support, pa_out);
- }
- 
--/* Return true if SF-NONE is present in factors. */
--static krb5_boolean
--contains_sf_none(krb5_spake_factor **factors)
--{
--    int i;
--
--    for (i = 0; factors != NULL && factors[i] != NULL; i++) {
--        if (factors[i]->type == SPAKE_SF_NONE)
--            return TRUE;
--    }
--    return FALSE;
--}
--
- static krb5_error_code
- process_challenge(krb5_context context, groupstate *gstate, reqstate *st,
-                   krb5_spake_challenge *ch, const krb5_data *der_msg,
-@@ -157,7 +185,7 @@ process_challenge(krb5_context context, groupstate *gstate, reqstate *st,
-                   const krb5_data *der_req, krb5_pa_data ***pa_out)
- {
-     krb5_error_code ret;
--    krb5_keyblock *k0 = NULL, *k1 = NULL;
-+    krb5_keyblock *k0 = NULL, *k1 = NULL, *as_key;
-     krb5_spake_factor factor;
-     krb5_pa_spake msg;
-     krb5_data *der_factor = NULL, *response;
-@@ -167,8 +195,8 @@ process_challenge(krb5_context context, groupstate *gstate, reqstate *st,
- 
-     enc_factor.ciphertext = empty_data();
- 
--    /* Not expected if we already computed the SPAKE result. */
--    if (st->spakeresult.length != 0)
-+    /* Not expected if we processed a challenge and didn't reject it. */
-+    if (st->initial_key != NULL)
-         return KRB5KDC_ERR_PREAUTH_FAILED;
- 
-     if (!group_is_permitted(gstate, ch->group)) {
-@@ -193,6 +221,12 @@ process_challenge(krb5_context context, groupstate *gstate, reqstate *st,
-     if (!contains_sf_none(ch->factors))
-         return KRB5KDC_ERR_PREAUTH_FAILED;
- 
-+    ret = cb->get_as_key(context, rock, &as_key);
-+    if (ret)
-+        goto cleanup;
-+    ret = krb5_copy_keyblock(context, as_key, &st->initial_key);
-+    if (ret)
-+        goto cleanup;
-     ret = derive_wbytes(context, ch->group, st->initial_key, &wbytes);
-     if (ret)
-         goto cleanup;
-@@ -267,7 +301,7 @@ process_encdata(krb5_context context, reqstate *st, krb5_enc_data *enc,
-                 krb5_pa_data ***pa_out)
- {
-     /* Not expected if we haven't sent a response yet. */
--    if (st->spakeresult.length == 0)
-+    if (st->initial_key == NULL || st->spakeresult.length == 0)
-         return KRB5KDC_ERR_PREAUTH_FAILED;
- 
-     /*
-@@ -292,9 +326,7 @@ spake_process(krb5_context context, krb5_clpreauth_moddata moddata,
-     krb5_error_code ret;
-     groupstate *gstate = (groupstate *)moddata;
-     reqstate *st = (reqstate *)modreq;
--    krb5_pa_spake *msg;
-     krb5_data in_data;
--    krb5_keyblock *as_key;
- 
-     if (st == NULL)
-         return ENOMEM;
-@@ -306,34 +338,23 @@ spake_process(krb5_context context, krb5_clpreauth_moddata moddata,
-         return send_support(context, gstate, st, pa_out);
-     }
- 
--    /* We need the initial reply key to process any non-trivial message. */
--    if (st->initial_key == NULL) {
--        ret = cb->get_as_key(context, rock, &as_key);
--        if (ret)
--            return ret;
--        ret = krb5_copy_keyblock(context, as_key, &st->initial_key);
--        if (ret)
--            return ret;
--    }
--
--    in_data = make_data(pa_in->contents, pa_in->length);
--    ret = decode_krb5_pa_spake(&in_data, &msg);
--    if (ret)
--        return ret;
--
--    if (msg->choice == SPAKE_MSGTYPE_CHALLENGE) {
--        ret = process_challenge(context, gstate, st, &msg->u.challenge,
-+    if (st->msg == NULL) {
-+        /* The message failed to decode in spake_prep_questions(). */
-+        ret = KRB5KDC_ERR_PREAUTH_FAILED;
-+    } else if (st->msg->choice == SPAKE_MSGTYPE_CHALLENGE) {
-+        in_data = make_data(pa_in->contents, pa_in->length);
-+        ret = process_challenge(context, gstate, st, &st->msg->u.challenge,
-                                 &in_data, cb, rock, prompter, prompter_data,
-                                 der_req, pa_out);
--    } else if (msg->choice == SPAKE_MSGTYPE_ENCDATA) {
--        ret = process_encdata(context, st, &msg->u.encdata, cb, rock, prompter,
--                              prompter_data, der_prev_req, der_req, pa_out);
-+    } else if (st->msg->choice == SPAKE_MSGTYPE_ENCDATA) {
-+        ret = process_encdata(context, st, &st->msg->u.encdata, cb, rock,
-+                              prompter, prompter_data, der_prev_req, der_req,
-+                              pa_out);
-     } else {
-         /* Unexpected message type */
-         ret = KRB5KDC_ERR_PREAUTH_FAILED;
-     }
- 
--    k5_free_pa_spake(context, msg);
-     return ret;
- }
- 
diff --git a/SOURCES/Become-FIPS-aware-with-3DES.patch b/SOURCES/Become-FIPS-aware-with-3DES.patch
new file mode 100644
index 0000000..02ffa7b
--- /dev/null
+++ b/SOURCES/Become-FIPS-aware-with-3DES.patch
@@ -0,0 +1,183 @@
+From 0c361343839b2ff6f89f1ee9c1e01d4f05ab6ffe Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Fri, 9 Nov 2018 15:12:21 -0500
+Subject: [PATCH] Become FIPS-aware (with 3DES)
+
+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 crypto we care about - which is to say that
+AES is fine.
+
+(cherry picked from commit 9f5fbf191d74cae9b28d318fff4c80d3d3e49c86)
+---
+ src/lib/crypto/openssl/enc_provider/camellia.c  |  6 ++++++
+ src/lib/crypto/openssl/enc_provider/des.c       |  9 +++++++++
+ src/lib/crypto/openssl/enc_provider/des3.c      |  6 ++++++
+ src/lib/crypto/openssl/enc_provider/rc4.c       | 13 ++++++++++++-
+ src/lib/crypto/openssl/hash_provider/hash_evp.c |  4 ++++
+ src/lib/crypto/openssl/hmac.c                   |  6 +++++-
+ 6 files changed, 42 insertions(+), 2 deletions(-)
+
+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/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/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c
+index 7f3c086ed..a3f2a7442 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) ? (struct arcfour_state *) 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 = (struct arcfour_state *) state->data;
++    struct arcfour_state *arcstate;
++
++    if (FIPS_mode())
++        return;
++
++    arcstate = (struct arcfour_state *) 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;
++
+     /* Create a state structure with an uninitialized context. */
+     arcstate = calloc(1, sizeof(*arcstate));
+     if (arcstate == NULL)
+diff --git a/src/lib/crypto/openssl/hash_provider/hash_evp.c b/src/lib/crypto/openssl/hash_provider/hash_evp.c
+index 957ed8d9c..8c1fd7f59 100644
+--- a/src/lib/crypto/openssl/hash_provider/hash_evp.c
++++ b/src/lib/crypto/openssl/hash_provider/hash_evp.c
+@@ -64,12 +64,16 @@ 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)
+ {
++    if (FIPS_mode())
++        return KRB5_CRYPTO_INTERNAL;
+     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/SOURCES/Become-FIPS-aware.patch b/SOURCES/Become-FIPS-aware.patch
deleted file mode 100644
index e87f8a3..0000000
--- a/SOURCES/Become-FIPS-aware.patch
+++ /dev/null
@@ -1,156 +0,0 @@
-From ce06474e3b12430480374f923c25bae9581fb146 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Fri, 9 Nov 2018 15:12:21 -0500
-Subject: [PATCH] Become FIPS-aware
-
-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 crypto we care about - AES is fine, for
-instance.
----
- src/lib/crypto/openssl/enc_provider/camellia.c  |  6 ++++++
- src/lib/crypto/openssl/enc_provider/des.c       |  9 +++++++++
- src/lib/crypto/openssl/enc_provider/rc4.c       | 13 ++++++++++++-
- src/lib/crypto/openssl/hash_provider/hash_evp.c |  4 ++++
- src/lib/crypto/openssl/hmac.c                   |  6 +++++-
- 5 files changed, 36 insertions(+), 2 deletions(-)
-
-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/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/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c
-index 7f3c086ed..a3f2a7442 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) ? (struct arcfour_state *) 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 = (struct arcfour_state *) state->data;
-+    struct arcfour_state *arcstate;
-+
-+    if (FIPS_mode())
-+        return;
-+
-+    arcstate = (struct arcfour_state *) 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;
-+
-     /* Create a state structure with an uninitialized context. */
-     arcstate = calloc(1, sizeof(*arcstate));
-     if (arcstate == NULL)
-diff --git a/src/lib/crypto/openssl/hash_provider/hash_evp.c b/src/lib/crypto/openssl/hash_provider/hash_evp.c
-index 957ed8d9c..8c1fd7f59 100644
---- a/src/lib/crypto/openssl/hash_provider/hash_evp.c
-+++ b/src/lib/crypto/openssl/hash_provider/hash_evp.c
-@@ -64,12 +64,16 @@ 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)
- {
-+    if (FIPS_mode())
-+        return KRB5_CRYPTO_INTERNAL;
-     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/SOURCES/Convert-Python-tests-to-Python-3.patch b/SOURCES/Convert-Python-tests-to-Python-3.patch
deleted file mode 100644
index 5f5dc23..0000000
--- a/SOURCES/Convert-Python-tests-to-Python-3.patch
+++ /dev/null
@@ -1,536 +0,0 @@
-From 2bc365f12282cdd83a191478b97f4ea0d9aa60dd Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Mon, 19 Feb 2018 21:10:09 -0500
-Subject: [PATCH] Convert Python tests to Python 3
-
-Look for python3 in configure.in and verify that we got it.  Convert
-test code to conform to Python 3.
-
-ticket: 8710 (new)
-(cherry picked from commit e23d24beacb73581bbf4351250f3955e6fd44361)
-[rharwood@redhat.com: Context skew due to not having LMDB in tests]
----
- src/Makefile.in                  |  1 +
- src/configure.in                 |  6 ++--
- src/kadmin/dbutil/t_tdumputil.py |  4 +--
- src/tests/jsonwalker.py          | 16 +++++------
- src/tests/t_cve-2012-1014.py     |  2 +-
- src/tests/t_cve-2012-1015.py     |  2 +-
- src/tests/t_hostrealm.py         |  4 ++-
- src/tests/t_kdb.py               | 11 ++++---
- src/tests/t_keytab.py            | 34 +++++++++++-----------
- src/tests/t_mkey.py              |  6 ++--
- src/tests/t_otp.py               |  7 +++--
- src/tests/t_tabdump.py           |  4 +--
- src/util/Makefile.in             |  1 +
- src/util/k5test.py               | 49 +++++++++++++++++---------------
- src/util/princflags.py           | 25 ++++++++--------
- 15 files changed, 88 insertions(+), 84 deletions(-)
-
-diff --git a/src/Makefile.in b/src/Makefile.in
-index 77beff8bc..79b8d5f98 100644
---- a/src/Makefile.in
-+++ b/src/Makefile.in
-@@ -533,6 +533,7 @@ runenv.py: pyrunenv.vals
- 
- clean-unix::
- 	$(RM) runenv.py runenv.pyc pyrunenv.vals
-+	$(RM) -r __pycache__
- 
- COV_BUILD=	cov-build
- COV_ANALYZE=	cov-analyze
-diff --git a/src/configure.in b/src/configure.in
-index 3f45784b5..00cb297b8 100644
---- a/src/configure.in
-+++ b/src/configure.in
-@@ -1098,15 +1098,13 @@ fi
- AC_SUBST(HAVE_RUNTEST)
- 
- # For Python tests.
--AC_CHECK_PROG(PYTHON,python2,python2)
-+AC_CHECK_PROG(PYTHON,python3,python3)
- if text x"$PYTHON" = x; then
- 	AC_CHECK_PROG(PYTHON,python,python)
- fi
- HAVE_PYTHON=no
- if test x"$PYTHON" != x; then
--	# k5test.py requires python 2.4 (for the subprocess module).
--	# Some code needs python 2.5 (for syntax like conditional expressions).
--	wantver="(sys.hexversion >= 0x2050000 and sys.hexversion < 0x3000000)"
-+	wantver="(sys.hexversion >= 0x3000000)"
- 	if "$PYTHON" -c "import sys; sys.exit(not $wantver and 1 or 0)"; then
- 		HAVE_PYTHON=yes
- 	fi
-diff --git a/src/kadmin/dbutil/t_tdumputil.py b/src/kadmin/dbutil/t_tdumputil.py
-index 52e356533..47b2aa7a3 100755
---- a/src/kadmin/dbutil/t_tdumputil.py
-+++ b/src/kadmin/dbutil/t_tdumputil.py
-@@ -6,8 +6,8 @@ realm = K5Realm(create_kdb=False)
- def compare(s, expected, msg):
-     if s == expected:
-         return
--    print 'expected:', repr(expected)
--    print 'got:', repr(s)
-+    print('expected:', repr(expected))
-+    print('got:', repr(s))
-     fail(msg)
- 
- out = realm.run(['./t_tdumputil', '2', 'field1', 'field2',
-diff --git a/src/tests/jsonwalker.py b/src/tests/jsonwalker.py
-index 942ca2db7..7a0675e08 100644
---- a/src/tests/jsonwalker.py
-+++ b/src/tests/jsonwalker.py
-@@ -2,8 +2,8 @@ import sys
- try:
-     import cjson
- except ImportError:
--    print "Warning: skipping audit log verification because the cjson module" \
--          " is unavailable"
-+    print("Warning: skipping audit log verification because the cjson module" \
-+          " is unavailable")
-     sys.exit(0)
- from collections import defaultdict
- from optparse import OptionParser
-@@ -22,10 +22,10 @@ class Parser(object):
-         result = self.parse(logs)
-         if len(result) != len(self.defaults):
-             diff = set(self.defaults.keys()).difference(result.keys())
--            print 'Test failed.'
--            print 'The following attributes were not set:'
-+            print('Test failed.')
-+            print('The following attributes were not set:')
-             for it in diff:
--                print it
-+                print(it)
-             sys.exit(1)
- 
-     def flatten(self, defaults):
-@@ -42,7 +42,7 @@ class Parser(object):
-         result = dict()
-         for path,value in self._walk(defaults):
-             if path in result:
--                print 'Warning: attribute path %s already exists' % path
-+                print('Warning: attribute path %s already exists' % path)
-             result[path] = value
- 
-         return result
-@@ -60,7 +60,7 @@ class Parser(object):
-                         if v is not None:
-                             dv = self.DEFAULTS[type(v)]
-                         else:
--                            print 'Warning: attribute %s is set to None' % a
-+                            print('Warning: attribute %s is set to None' % a)
-                             continue
-                     # by now we have default value
-                     if v != dv:
-@@ -96,7 +96,7 @@ if __name__ == '__main__':
-                 content.append(cjson.decode(l.rstrip()))
-         f.close()
-     else:
--        print 'Input file in jason format is required'
-+        print('Input file in jason format is required')
-         exit()
- 
-     defaults = None
-diff --git a/src/tests/t_cve-2012-1014.py b/src/tests/t_cve-2012-1014.py
-index dcff95f6e..8447e0ee7 100755
---- a/src/tests/t_cve-2012-1014.py
-+++ b/src/tests/t_cve-2012-1014.py
-@@ -20,7 +20,7 @@ x2 = base64.b16decode('A44F304DA007030500FEDCBA90A10E30' +
-                       '01')
- 
- for x in range(11, 128):
--    s.sendto(''.join([x1, chr(x), x2]), a)
-+    s.sendto(x1 + bytes([x]) + x2, a)
- 
- # Make sure kinit still works.
- 
-diff --git a/src/tests/t_cve-2012-1015.py b/src/tests/t_cve-2012-1015.py
-index 28b1e619b..ae5678cac 100755
---- a/src/tests/t_cve-2012-1015.py
-+++ b/src/tests/t_cve-2012-1015.py
-@@ -27,7 +27,7 @@ x1 = base64.b16decode('6A81A030819DA103020105A20302010A' +
- x2 = base64.b16decode('A8083006020106020112')
- 
- for x in range(0, 128):
--    s.sendto(''.join([x1, chr(x), x2]), a)
-+    s.sendto(x1 + bytes([x]) + x2, a)
- 
- # Make sure kinit still works.
- 
-diff --git a/src/tests/t_hostrealm.py b/src/tests/t_hostrealm.py
-index 256ba2a38..beea6f3bc 100755
---- a/src/tests/t_hostrealm.py
-+++ b/src/tests/t_hostrealm.py
-@@ -119,7 +119,9 @@ testd(realm, 'KRBTEST.COM', 'default_realm profile', env=notest2)
- # see the first.  Remove the profile default_realm setting to expose
- # this behavior.
- remove_default = {'libdefaults': {'default_realm': None}}
--nodefault_conf = dict(disable_conf.items() + remove_default.items())
-+# Python 3.5+: nodefault_conf = {**disable_conf, **remove_default}
-+nodefault_conf = dict(list(disable_conf.items()) +
-+                      list(remove_default.items()))
- nodefault = realm.special_env('nodefault', False, krb5_conf=nodefault_conf)
- testd(realm, 'one', 'default_realm test1', env=nodefault)
- 
-diff --git a/src/tests/t_kdb.py b/src/tests/t_kdb.py
-index 983cd93c8..42237f7a1 100755
---- a/src/tests/t_kdb.py
-+++ b/src/tests/t_kdb.py
-@@ -1,6 +1,5 @@
- from k5test import *
- import time
--from itertools import imap
- 
- # Run kdbtest against the BDB module.
- realm = K5Realm(create_kdb=False)
-@@ -51,7 +50,7 @@ else:
- def slap_add(ldif):
-     proc = subprocess.Popen([slapadd, '-b', 'cn=config', '-F', slapd_conf],
-                             stdin=subprocess.PIPE, stdout=subprocess.PIPE,
--                            stderr=subprocess.STDOUT)
-+                            stderr=subprocess.STDOUT, universal_newlines=True)
-     (out, dummy) = proc.communicate(ldif)
-     output(out)
-     return proc.wait()
-@@ -98,7 +97,7 @@ if slap_add('include: file://%s\n' % schema) != 0:
- ldap_homes = ['/etc/ldap', '/etc/openldap', '/usr/local/etc/openldap',
-               '/usr/local/etc/ldap']
- local_schema_path = '/schema/core.ldif'
--core_schema = next((i for i in imap(lambda x:x+local_schema_path, ldap_homes)
-+core_schema = next((i for i in map(lambda x:x+local_schema_path, ldap_homes)
-                     if os.path.isfile(i)), None)
- if core_schema:
-     if slap_add('include: file://%s\n' % core_schema) != 0:
-@@ -114,7 +113,7 @@ atexit.register(kill_slapd)
- 
- out = open(slapd_out, 'w')
- subprocess.call([slapd, '-h', ldap_uri, '-F', slapd_conf], stdout=out,
--                stderr=out)
-+                stderr=out, universal_newlines=True)
- out.close()
- pidf = open(slapd_pidfile, 'r')
- slapd_pid = int(pidf.read())
-@@ -158,7 +157,7 @@ def ldap_search(args):
-     proc = subprocess.Popen([ldapsearch, '-H', ldap_uri, '-b', top_dn,
-                              '-D', admin_dn, '-w', admin_pw, args],
-                             stdin=subprocess.PIPE, stdout=subprocess.PIPE,
--                            stderr=subprocess.STDOUT)
-+                            stderr=subprocess.STDOUT, universal_newlines=True)
-     (out, dummy) = proc.communicate()
-     return out
- 
-@@ -166,7 +165,7 @@ def ldap_modify(ldif, args=[]):
-     proc = subprocess.Popen([ldapmodify, '-H', ldap_uri, '-D', admin_dn,
-                              '-x', '-w', admin_pw] + args,
-                             stdin=subprocess.PIPE, stdout=subprocess.PIPE,
--                            stderr=subprocess.STDOUT)
-+                            stderr=subprocess.STDOUT, universal_newlines=True)
-     (out, dummy) = proc.communicate(ldif)
-     output(out)
- 
-diff --git a/src/tests/t_keytab.py b/src/tests/t_keytab.py
-index 228c36334..8a17ae2eb 100755
---- a/src/tests/t_keytab.py
-+++ b/src/tests/t_keytab.py
-@@ -90,36 +90,36 @@ test_key_rotate(realm, princ, 2)
- 
- # Test that klist -k can read a keytab entry without a 32-bit kvno and
- # reports the 8-bit key version.
--record = '\x00\x01'             # principal component count
--record += '\x00\x0bKRBTEST.COM' # realm
--record += '\x00\x04user'        # principal component
--record += '\x00\x00\x00\x01'    # name type (NT-PRINCIPAL)
--record += '\x54\xf7\x4d\x35'    # timestamp
--record += '\x02'                # key version
--record += '\x00\x12'            # enctype
--record += '\x00\x20'            # key length
--record += '\x00' * 32           # key bytes
--f = open(realm.keytab, 'w')
--f.write('\x05\x02\x00\x00\x00' + chr(len(record)))
-+record = b'\x00\x01'             # principal component count
-+record += b'\x00\x0bKRBTEST.COM' # realm
-+record += b'\x00\x04user'        # principal component
-+record += b'\x00\x00\x00\x01'    # name type (NT-PRINCIPAL)
-+record += b'\x54\xf7\x4d\x35'    # timestamp
-+record += b'\x02'                # key version
-+record += b'\x00\x12'            # enctype
-+record += b'\x00\x20'            # key length
-+record += b'\x00' * 32           # key bytes
-+f = open(realm.keytab, 'wb')
-+f.write(b'\x05\x02\x00\x00\x00' + bytes([len(record)]))
- f.write(record)
- f.close()
- msg = '   2 %s' % realm.user_princ
- out = realm.run([klist, '-k'], expected_msg=msg)
- 
- # Make sure zero-fill isn't treated as a 32-bit kvno.
--f = open(realm.keytab, 'w')
--f.write('\x05\x02\x00\x00\x00' + chr(len(record) + 4))
-+f = open(realm.keytab, 'wb')
-+f.write(b'\x05\x02\x00\x00\x00' + bytes([len(record) + 4]))
- f.write(record)
--f.write('\x00\x00\x00\x00')
-+f.write(b'\x00\x00\x00\x00')
- f.close()
- msg = '   2 %s' % realm.user_princ
- out = realm.run([klist, '-k'], expected_msg=msg)
- 
- # Make sure a hand-crafted 32-bit kvno is recognized.
--f = open(realm.keytab, 'w')
--f.write('\x05\x02\x00\x00\x00' + chr(len(record) + 4))
-+f = open(realm.keytab, 'wb')
-+f.write(b'\x05\x02\x00\x00\x00' + bytes([len(record) + 4]))
- f.write(record)
--f.write('\x00\x00\x00\x03')
-+f.write(b'\x00\x00\x00\x03')
- f.close()
- msg = '   3 %s' % realm.user_princ
- out = realm.run([klist, '-k'], expected_msg=msg)
-diff --git a/src/tests/t_mkey.py b/src/tests/t_mkey.py
-index 48a533059..cbc830235 100755
---- a/src/tests/t_mkey.py
-+++ b/src/tests/t_mkey.py
-@@ -296,10 +296,10 @@ realm.stop()
- # 2. list_mkeys displays the same list as for a post-1.7 KDB.
- dumpfile = os.path.join(srctop, 'tests', 'dumpfiles', 'dump.16')
- os.remove(stash_file)
--f = open(stash_file, 'w')
-+f = open(stash_file, 'wb')
- f.write(struct.pack('=HL24s', 16, 24,
--                    '\xF8\x3E\xFB\xBA\x6D\x80\xD9\x54\xE5\x5D\xF2\xE0'
--                    '\x94\xAD\x6D\x86\xB5\x16\x37\xEC\x7C\x8A\xBC\x86'))
-+                    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())
-diff --git a/src/tests/t_otp.py b/src/tests/t_otp.py
-index 0fd35d576..617a8ecf5 100755
---- a/src/tests/t_otp.py
-+++ b/src/tests/t_otp.py
-@@ -29,8 +29,8 @@
- #
- 
- from k5test import *
--from Queue import Empty
--import StringIO
-+from queue import Empty
-+from io import StringIO
- import struct
- 
- try:
-@@ -120,7 +120,8 @@ class UnixRadiusDaemon(RadiusDaemon):
-         sock.listen(1)
-         return (sock, addr)
- 
--    def recvRequest(self, (sock, addr)):
-+    def recvRequest(self, sock_and_addr):
-+        sock, addr = sock_and_addr
-         conn = sock.accept()[0]
-         sock.close()
-         os.remove(addr)
-diff --git a/src/tests/t_tabdump.py b/src/tests/t_tabdump.py
-index 2a86136dd..49531bf49 100755
---- a/src/tests/t_tabdump.py
-+++ b/src/tests/t_tabdump.py
-@@ -1,10 +1,10 @@
- from k5test import *
- 
- import csv
--import StringIO
-+from io import StringIO
- 
- def tab_csv(s):
--    io = StringIO.StringIO(s)
-+    io = StringIO(s)
-     return list(csv.DictReader(io, dialect=csv.excel_tab))
- 
- 
-diff --git a/src/util/Makefile.in b/src/util/Makefile.in
-index 2611581c1..19a6bd312 100644
---- a/src/util/Makefile.in
-+++ b/src/util/Makefile.in
-@@ -26,3 +26,4 @@ install:
- 
- clean-unix::
- 	$(RM) *.pyc
-+	$(RM) -r __pycache__
-diff --git a/src/util/k5test.py b/src/util/k5test.py
-index bc32877a7..81fac3063 100644
---- a/src/util/k5test.py
-+++ b/src/util/k5test.py
-@@ -380,16 +380,16 @@ import imp
- def fail(msg):
-     """Print a message and exit with failure."""
-     global _current_pass
--    print "*** Failure:", msg
-+    print("*** Failure:", msg)
-     if _last_mark:
--        print "*** Last mark: %s" % _last_mark
-+        print("*** Last mark: %s" % _last_mark)
-     if _last_cmd:
--        print "*** Last command (#%d): %s" % (_cmd_index - 1, _last_cmd)
-+        print("*** Last command (#%d): %s" % (_cmd_index - 1, _last_cmd))
-     if _last_cmd_output:
--        print "*** Output of last command:"
-+        print("*** Output of last command:")
-         sys.stdout.write(_last_cmd_output)
-     if _current_pass:
--        print "*** Failed in test pass:", _current_pass
-+        print("*** Failed in test pass:", _current_pass)
-     sys.exit(1)
- 
- 
-@@ -465,15 +465,16 @@ def _onexit():
-         if not verbose:
-             testlogfile = os.path.join(os.getcwd(), 'testlog')
-             utildir = os.path.join(srctop, 'util')
--            print 'For details, see: %s' % testlogfile
--            print 'Or re-run this test script with the -v flag:'
--            print '    cd %s' % os.getcwd()
--            print '    PYTHONPATH=%s %s %s -v' % \
--                (utildir, sys.executable, sys.argv[0])
--            print
--        print 'Use --debug=NUM to run a command under a debugger.  Use'
--        print '--stop-after=NUM to stop after a daemon is started in order to'
--        print 'attach to it with a debugger.  Use --help to see other options.'
-+            print('For details, see: %s' % testlogfile)
-+            print('Or re-run this test script with the -v flag:')
-+            print('    cd %s' % os.getcwd())
-+            print('    PYTHONPATH=%s %s %s -v' %
-+                  (utildir, sys.executable, sys.argv[0]))
-+            print()
-+        print('Use --debug=NUM to run a command under a debugger.  Use')
-+        print('--stop-after=NUM to stop after a daemon is started in order to')
-+        print('attach to it with a debugger.  Use --help to see other')
-+        print('options.')
- 
- 
- def _onsigint(signum, frame):
-@@ -523,8 +524,8 @@ def _get_hostname():
-     hostname = socket.gethostname()
-     try:
-         ai = socket.getaddrinfo(hostname, None, 0, 0, 0, socket.AI_CANONNAME)
--    except socket.gaierror, (error, errstr):
--        fail('Local hostname "%s" does not resolve: %s.' % (hostname, errstr))
-+    except socket.gaierror as e:
-+        fail('Local hostname "%s" does not resolve: %s.' % (hostname, e[1]))
-     (family, socktype, proto, canonname, sockaddr) = ai[0]
-     try:
-         name = socket.getnameinfo(sockaddr, socket.NI_NAMEREQD)
-@@ -594,7 +595,7 @@ def _match_cmdnum(cmdnum, ind):
- def _build_env():
-     global buildtop, runenv
-     env = os.environ.copy()
--    for (k, v) in runenv.env.iteritems():
-+    for (k, v) in runenv.env.items():
-         if v.find('./') == 0:
-             env[k] = os.path.join(buildtop, v)
-         else:
-@@ -704,7 +705,8 @@ def _run_cmd(args, env, input=None, expected_code=0, expected_msg=None,
- 
-     # Run the command and log the result, folding stderr into stdout.
-     proc = subprocess.Popen(args, stdin=infile, stdout=subprocess.PIPE,
--                            stderr=subprocess.STDOUT, env=env)
-+                            stderr=subprocess.STDOUT, env=env,
-+                            universal_newlines=True)
-     (outdata, dummy_errdata) = proc.communicate(input)
-     _last_cmd_output = outdata
-     code = proc.returncode
-@@ -734,10 +736,10 @@ def _debug_cmd(args, env, input):
-            (_cmd_index, _shell_equiv(args)), True)
-     if input:
-         print
--        print '*** Enter the following input when appropriate:'
--        print 
--        print input
--        print
-+        print('*** Enter the following input when appropriate:')
-+        print()
-+        print(input)
-+        print()
-     code = subprocess.call(args, env=env)
-     output('*** [%d] Completed in debugger with return code %d\n' %
-            (_cmd_index, code))
-@@ -765,7 +767,8 @@ def _start_daemon(args, env, sentinel):
- 
-     # Start the daemon and look for the sentinel in stdout or stderr.
-     proc = subprocess.Popen(args, stdin=null_input, stdout=subprocess.PIPE,
--                            stderr=subprocess.STDOUT, env=env)
-+                            stderr=subprocess.STDOUT, env=env,
-+                            universal_newlines=True)
-     _last_cmd_output = ''
-     while True:
-         line = proc.stdout.readline()
-diff --git a/src/util/princflags.py b/src/util/princflags.py
-index f568dd2f1..f645e86e4 100644
---- a/src/util/princflags.py
-+++ b/src/util/princflags.py
-@@ -1,5 +1,4 @@
- import re
--import string
- 
- # Module for translating KDB principal flags between string and
- # integer forms.
-@@ -81,7 +80,7 @@ _prefixlen = len(_prefix)
- _flagnames = {}
- 
- # Translation table to map hyphens to underscores
--_squash = string.maketrans('-', '_')
-+_squash = str.maketrans('-', '_')
- 
- # Combined input-to-flag lookup table, to be filled in by
- # _setup_tables()
-@@ -176,7 +175,7 @@ def flagnum2str(n):
- # Return a list of flag names from a flag word.
- def flags2namelist(flags):
-     a = []
--    for n in xrange(32):
-+    for n in range(32):
-         if flags & (1 << n):
-             a.append(flagnum2str(n))
-     return a
-@@ -225,21 +224,21 @@ def speclist2mask(s):
- 
- # Print C table of input flag specifiers for lib/kadm5/str_conv.c.
- def _print_ftbl():
--    print 'static const struct flag_table_row ftbl[] = {'
--    a = sorted(pflags.items(), key=lambda (k, v): (v.flag, -v.invert, k))
-+    print('static const struct flag_table_row ftbl[] = {')
-+    a = sorted(pflags.items(), key=lambda k, v: (v.flag, -v.invert, k))
-     for k, v in a:
-         s1 = '    {"%s",' % k
-         s2 = '%-31s KRB5_KDB_%s,' % (s1, v.flagname())
--        print '%-63s %d},' % (s2, 1 if v.invert else 0)
-+        print('%-63s %d},' % (s2, 1 if v.invert else 0))
- 
--    print '};'
--    print '#define NFTBL (sizeof(ftbl) / sizeof(ftbl[0]))'
-+    print('};')
-+    print('#define NFTBL (sizeof(ftbl) / sizeof(ftbl[0]))')
- 
- 
- # Print C table of output flag names for lib/kadm5/str_conv.c.
- def _print_outflags():
--    print 'static const char *outflags[] = {'
--    for i in xrange(32):
-+    print('static const char *outflags[] = {')
-+    for i in range(32):
-         flag = 1 << i
-         if flag > max(_flagnames.keys()):
-             break
-@@ -247,10 +246,10 @@ def _print_outflags():
-             s = '    "%s",' % _flagnames[flag]
-         except KeyError:
-             s = '    NULL,'
--        print '%-32s/* 0x%08x */' % (s, flag)
-+        print('%-32s/* 0x%08x */' % (s, flag))
- 
--    print '};'
--    print '#define NOUTFLAGS (sizeof(outflags) / sizeof(outflags[0]))'
-+    print('};')
-+    print('#define NOUTFLAGS (sizeof(outflags) / sizeof(outflags[0]))')
- 
- 
- # Print out C tables to insert into lib/kadm5/str_conv.c.
diff --git a/SOURCES/Eliminate-preprocessor-disabled-dead-code.patch b/SOURCES/Eliminate-preprocessor-disabled-dead-code.patch
deleted file mode 100644
index 9c55c67..0000000
--- a/SOURCES/Eliminate-preprocessor-disabled-dead-code.patch
+++ /dev/null
@@ -1,2950 +0,0 @@
-From 904a5789da342857a50de5874fe6aae1f96cbc5c Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Mon, 16 Jul 2018 15:35:15 -0400
-Subject: [PATCH] Eliminate preprocessor-disabled dead code
-
-It's been policy for a while now not to create "dead hunks" like
-these.  A great deal of this code simply doesn't work because it
-hasn't been kept up-to-date, and may never have worked.  Eliminate
-these dead hunks along with the complexity to support them.
-
-(cherry picked from commit 2bc951d3c88b460a16249115cbd51d69c3c57e22)
-[rharwood@redhat.com: context skew]
----
- src/ccapi/common/win/OldCC/ccutils.c          |  6 --
- src/ccapi/common/win/OldCC/ccutils.h          |  3 -
- src/ccapi/common/win/OldCC/opts.cxx           | 39 ----------
- src/ccapi/common/win/OldCC/secure.hxx         |  6 --
- src/ccapi/common/win/OldCC/util.h             |  3 -
- src/ccapi/lib/win/OldCC/client.cxx            | 39 ----------
- src/ccapi/lib/win/ccapi_os_ipc.cxx            | 15 ----
- src/ccapi/lib/win/ccs_reply_proc.c            |  8 +-
- src/ccapi/lib/win/dllmain.cxx                 | 12 +--
- src/ccapi/server/win/ccs_os_server.cpp        | 23 +-----
- src/ccapi/server/win/ccs_request_proc.c       | 12 +--
- src/ccapi/server/win/ccs_win_pipe.c           |  4 +-
- src/ccapi/test/pingtest.c                     |  6 --
- src/clients/ksu/authorization.c               | 17 -----
- src/config/win-post.in                        |  8 --
- src/include/gssrpc/auth.h                     | 15 ----
- src/include/gssrpc/rename.h                   | 26 +------
- src/include/gssrpc/rpc.h                      | 25 -------
- src/include/gssrpc/types.hin                  |  7 --
- src/include/k5-platform.h                     | 28 +------
- src/kadmin/dbutil/kdb5_util.c                 | 38 ----------
- src/kadmin/server/ipropd_svc.c                | 29 -------
- src/kdc/kdc_log.c                             |  8 --
- src/kdc/kdc_preauth.c                         | 13 ----
- src/lib/apputils/net-server.c                 | 27 -------
- src/lib/crypto/builtin/des/destest.c          |  4 -
- src/lib/crypto/builtin/des/t_verify.c         | 24 ------
- src/lib/crypto/builtin/pbkdf2.c               | 38 +---------
- src/lib/crypto/builtin/sha1/t_shs.c           | 15 ----
- src/lib/crypto/crypto_tests/t_cksums.c        |  4 -
- src/lib/crypto/crypto_tests/t_crc.c           | 45 +----------
- src/lib/crypto/crypto_tests/t_cts.c           | 27 -------
- src/lib/crypto/crypto_tests/t_decrypt.c       |  4 -
- src/lib/crypto/crypto_tests/t_derive.c        |  4 -
- src/lib/crypto/crypto_tests/t_hmac.c          | 11 ---
- src/lib/crypto/crypto_tests/t_str2key.c       |  4 -
- src/lib/crypto/crypto_tests/vectors.c         |  5 --
- src/lib/crypto/krb/nfold.c                    | 10 ---
- src/lib/gssapi/generic/util_set.c             | 15 ----
- src/lib/gssapi/krb5/accept_sec_context.c      | 11 ---
- src/lib/gssapi/krb5/gssapi_krb5.c             | 28 -------
- src/lib/gssapi/krb5/naming_exts.c             | 10 ---
- src/lib/gssapi/mechglue/g_initialize.c        | 25 -------
- src/lib/gssapi/mechglue/g_inq_cred.c          |  5 --
- src/lib/gssapi/mechglue/mglueP.h              |  5 --
- src/lib/kadm5/clnt/client_init.c              | 48 +-----------
- src/lib/kadm5/srv/server_init.c               | 11 ---
- src/lib/kadm5/unit-test/setkey-test.c         |  9 ---
- src/lib/krb5/asn.1/ldap_key_seq.c             |  3 -
- src/lib/krb5/ccache/ccapi/stdcc.c             | 58 --------------
- src/lib/krb5/ccache/ccapi/winccld.h           | 36 ---------
- src/lib/krb5/keytab/t_keytab.c                | 13 ----
- src/lib/krb5/krb/gc_via_tkt.c                 | 11 ---
- src/lib/krb5/krb/init_ctx.c                   |  7 --
- src/lib/krb5/krb/rd_req_dec.c                 | 31 +-------
- src/lib/krb5/krb/t_ser.c                      | 75 +------------------
- src/lib/krb5/krb/unparse.c                    |  7 --
- src/lib/krb5/os/localaddr.c                   | 22 ------
- src/lib/krb5/rcache/rc_io.c                   |  4 -
- src/lib/rpc/auth_gssapi.c                     |  8 --
- src/lib/rpc/svc_auth.c                        |  3 -
- src/lib/rpc/svc_auth_gssapi.c                 |  4 -
- src/lib/win_glue.c                            |  9 ---
- src/plugins/kdb/db2/lockout.c                 |  4 -
- src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c |  3 -
- src/plugins/preauth/pkinit/pkinit_clnt.c      | 18 -----
- src/plugins/preauth/pkinit/pkinit_matching.c  | 11 ---
- src/plugins/preauth/pkinit/pkinit_srv.c       | 18 -----
- src/tests/asn.1/krb5_decode_leak.c            | 12 ---
- src/tests/dejagnu/config/default.exp          | 20 -----
- src/tests/shlib/t_loader.c                    | 12 ---
- src/tests/threads/t_rcache.c                  |  6 --
- src/util/profile/prof_file.c                  | 43 -----------
- src/util/support/fake-addrinfo.c              |  6 --
- src/util/support/utf8.c                       | 22 ------
- src/windows/include/loadfuncs-krb5.h          | 23 ------
- src/windows/kfwlogon/kfwlogon.c               | 11 ---
- src/windows/leash/Leash.cpp                   |  4 -
- src/windows/leash/Makefile.in                 |  3 -
- src/windows/leash/VSroutines.c                | 64 ----------------
- src/windows/leashdll/lsh_pwd.c                | 11 ---
- src/windows/leashdll/lshfunc.c                | 32 +-------
- src/windows/leashdll/lshutil.cpp              | 11 ---
- src/windows/lib/cacheapi.h                    | 15 ----
- 84 files changed, 23 insertions(+), 1396 deletions(-)
- delete mode 100644 src/windows/leash/VSroutines.c
-
-diff --git a/src/ccapi/common/win/OldCC/ccutils.c b/src/ccapi/common/win/OldCC/ccutils.c
-index 13f72cbe0..403c67ebe 100644
---- a/src/ccapi/common/win/OldCC/ccutils.c
-+++ b/src/ccapi/common/win/OldCC/ccutils.c
-@@ -101,9 +101,6 @@ HANDLE createThreadEvent(char* uuid, char* suffix) {
-         event_name = allocEventName(uuid, suffix);
-         if (!event_name) status = cci_check_error(ccErrNoMem);
-         }
--#if 0
--    cci_debug_printf("%s event_name:%s", __FUNCTION__, event_name);
--#endif
-     if (!status) {
-         hEvent = CreateEvent(psa, FALSE, FALSE, event_name);
-         if (!hEvent)     status = cci_check_error(GetLastError());
-@@ -125,9 +122,6 @@ HANDLE openThreadEvent(char* uuid, char* suffix) {
- 
-     event_name = allocEventName(uuid, suffix);
-     if (!event_name) status = cci_check_error(ccErrNoMem);
--#if 0
--    cci_debug_printf("%s event_name:%s", __FUNCTION__, event_name);
--#endif
-     if (!status) {
-         hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, event_name);
-         if (!hEvent) status = cci_check_error(GetLastError());
-diff --git a/src/ccapi/common/win/OldCC/ccutils.h b/src/ccapi/common/win/OldCC/ccutils.h
-index f91c77702..9da3d87fd 100644
---- a/src/ccapi/common/win/OldCC/ccutils.h
-+++ b/src/ccapi/common/win/OldCC/ccutils.h
-@@ -29,9 +29,6 @@
- #ifdef __cplusplus
- extern "C" {
- #endif
--#if 0
--}
--#endif
- 
- #define REPLY_SUFFIX    (char*)"reply"
- #define LISTEN_SUFFIX   (char*)"listen"
-diff --git a/src/ccapi/common/win/OldCC/opts.cxx b/src/ccapi/common/win/OldCC/opts.cxx
-index bd5f503ea..c9776638b 100644
---- a/src/ccapi/common/win/OldCC/opts.cxx
-+++ b/src/ccapi/common/win/OldCC/opts.cxx
-@@ -29,45 +29,6 @@
- #include <stdlib.h>
- #include <opts.hxx>
- 
--#if 0
--const struct Opts*
--GetOpts(
--    )
--{
--    bool done = false;
--    struct Opts* o;
--    if (!(o = new Opts))
--        goto cleanup;
--    if (!(o->pszString = new char[lstrlenA(opts.pszString) + 1]))
--        goto cleanup;
--    if (!(o->pszEndpoint = new char[lstrlenA(opts.pszEndpoint) + 1]))
--        goto cleanup;
--    strcpy(o->pszString, opts.pszString);
--    strcpy(o->pszEndpoint, opts.pszEndpoint);
--    done = true;
-- cleanup:
--    if (!done) {
--        FreeOpts(o);
--        o = 0;
--    }
--    return o;
--}
--
--void
--FreeOpts(
--    struct Opts* o
--    )
--{
--    if (o) {
--        if (o->pszString)
--            delete [] o->pszString;
--        if (o->pszEndpoint)
--            delete [] o->pszEndpoint;
--        delete o;
--    }
--}
--#endif
--
- bool
- ParseOpts::IsValidOpt(
-     char ch
-diff --git a/src/ccapi/common/win/OldCC/secure.hxx b/src/ccapi/common/win/OldCC/secure.hxx
-index 3714c6f84..1b2e7532d 100644
---- a/src/ccapi/common/win/OldCC/secure.hxx
-+++ b/src/ccapi/common/win/OldCC/secure.hxx
-@@ -38,12 +38,6 @@ public:
-     static void Start(SecureClient*& s);
-     static void Stop(SecureClient*& s);
- 
--#if 0
--    static DWORD CheckImpersonation();
--    static bool IsImp();
--    static DWORD DuplicateImpAsPrimary(HANDLE& hPrimary);
--#endif
--
-     SecureClient();
-     ~SecureClient();
-     DWORD Error();
-diff --git a/src/ccapi/common/win/OldCC/util.h b/src/ccapi/common/win/OldCC/util.h
-index 082f6080b..45e069a71 100644
---- a/src/ccapi/common/win/OldCC/util.h
-+++ b/src/ccapi/common/win/OldCC/util.h
-@@ -29,9 +29,6 @@
- #ifdef __cplusplus
- extern "C" {
- #endif
--#if 0
--}
--#endif
- 
- BOOL isNT();
- 
-diff --git a/src/ccapi/lib/win/OldCC/client.cxx b/src/ccapi/lib/win/OldCC/client.cxx
-index 4b2d718cc..0f95dfceb 100644
---- a/src/ccapi/lib/win/OldCC/client.cxx
-+++ b/src/ccapi/lib/win/OldCC/client.cxx
-@@ -118,9 +118,6 @@ DWORD find_server(Init::InitInfo& info, LPSTR endpoint) {
-     char*               szDir       = 0;
-     BOOL                bRes        = FALSE;
-     char*               cmdline     = NULL;
--#if 0
--    HANDLE hToken = 0;
--#endif
- 
-     psa = isNT() ? &sa : 0;
- 
-@@ -156,38 +153,6 @@ DWORD find_server(Init::InitInfo& info, LPSTR endpoint) {
-             }
- 
-         if (!status) {
--
--#if 0
--            if (SecureClient::IsImp()) {
--                cci_debug_printf(STARTUP "Token is impersonation token"));
--                SecureClient::DuplicateImpAsPrimary(hToken);
--                } 
--            else {
--                cci_debug_printf(STARTUP "Token is NOT impersonation token"));
--                }
--#endif
--
--#if 0
--            if (hToken)
--                bRes = CreateProcessAsUser(hToken,
--                                       szExe, // app name
--                                       NULL, // cmd line
--                                       psa, // SA
--                                       psa, // SA
--                                       FALSE, 
--                                       CREATE_NEW_PROCESS_GROUP | 
--                                       //CREATE_NEW_CONSOLE |
--                                       NORMAL_PRIORITY_CLASS |
--                                       // CREATE_NO_WINDOW |
--                                       DETACHED_PROCESS |
--                                       0
--                                       ,
--                                       NULL, // environment
--                                       szDir, // current dir
--                                       &si,
--                                       &pi);
--            else
--#endif
-                 alloc_cmdline_2_args(szExe, endpoint, "-D", &cmdline);
-                 bRes = CreateProcess(  szExe,       // app name
-                                        NULL, //cmdline,     // cmd line is <server endpoint -[DC]>
-@@ -223,10 +188,6 @@ DWORD find_server(Init::InitInfo& info, LPSTR endpoint) {
-             cci_debug_printf("  unexpected error while looking for server: 0D%d / 0U%u / 0X%X", status, status, status);
-             } 
- 
--#if 0
--    if (hToken)
--        CloseHandle(hToken);
--#endif
-     if (szDir)                      free_alloc_p(&szDir);
-     if (szExe)                      free_alloc_p(&szExe);
-     if (hEvent)                     CloseHandle(hEvent);
-diff --git a/src/ccapi/lib/win/ccapi_os_ipc.cxx b/src/ccapi/lib/win/ccapi_os_ipc.cxx
-index 35589a54f..1b1f874e9 100644
---- a/src/ccapi/lib/win/ccapi_os_ipc.cxx
-+++ b/src/ccapi/lib/win/ccapi_os_ipc.cxx
-@@ -132,9 +132,6 @@ extern "C" cc_int32 cci_os_ipc_thread_init (void) {
-         cci_check_error(err);
-         }
- 
--#if 0
--    cci_debug_printf("%s UUID:<%s>", __FUNCTION__, tspdata_getUUID(ptspdata));
--#endif
-     // Initialize old CCAPI if necessary:
-     if (!err) if (!Init::  Initialized()) err = Init::  Initialize( );
-     if (!err) if (!Client::Initialized()) err = Client::Initialize(0);
-@@ -243,10 +240,6 @@ extern "C" cc_int32 cci_os_ipc_msg( cc_int32        in_launch_server,
-             if (!GetTspData(GetTlsIndex(), &ptspdata)) {return ccErrBadParam;}
-             uuid    = tspdata_getUUID(ptspdata);
-             lenUUID = 1 + strlen(uuid);     /* 1+ includes terminating \0. */
--#if 0
--            cci_debug_printf("%s calling remote ccs_rpc_request tsp*:0x%X", __FUNCTION__, ptspdata);
--            cci_debug_printf("  rpcmsg:%d; UUID[%d]:<%s> SST:%ld", in_msg, lenUUID, uuid, sst);
--#endif
-             /* copy ptr into handle; ptr may be 4 or 8 bytes, depending on platform; handle is always 8 */
-             memcpy(tspdata_handle, &ptspdata, sizeof(ptspdata));
-             ccs_rpc_request(                    /* make call with user message: */
-@@ -282,11 +275,6 @@ extern "C" cc_int32 cci_os_ipc_msg( cc_int32        in_launch_server,
-     if (!err && server_died) {
-         err = cci_check_error (ccErrServerUnavailable);
-         }
--#if 0    
--    if (err == BOOTSTRAP_UNKNOWN_SERVICE && !in_launch_server) {
--        err = ccNoError;  /* If the server is not running just return an empty stream. */
--        }
--#endif
- 
-     if (!err) {
-         *out_reply_stream = tspdata_getStream(ptspdata);
-@@ -365,9 +353,6 @@ cc_int32 ccapi_connect(const struct tspdata* tsp) {
-     ReleaseMutex(hCCAPIv2Mutex);       
- 
-     if (!status) {
--#if 0
--        cci_debug_printf("%s Waiting for replyEvent.", __FUNCTION__);
--#endif
-         status = WaitForSingleObject(replyEvent, INFINITE);//(SECONDS_TO_WAIT)*1000);
-         status = cci_check_error(RpcMgmtIsServerListening(CLIENT_REQUEST_RPC_HANDLE));
-         cci_debug_printf("  Server %sFOUND!", (status) ? "NOT " : "");
-diff --git a/src/ccapi/lib/win/ccs_reply_proc.c b/src/ccapi/lib/win/ccs_reply_proc.c
-index bf8c7f4f4..b4dbc0d19 100644
---- a/src/ccapi/lib/win/ccs_reply_proc.c
-+++ b/src/ccapi/lib/win/ccs_reply_proc.c
-@@ -47,9 +47,7 @@ void ccs_rpc_request_reply(
-     struct tspdata* tsp;
-     k5_ipc_stream    stream;
-     long            status  = 0;
--#if 0
--    cci_debug_printf("%s! msg#:%d SST:%ld uuid:%s", __FUNCTION__, rpcmsg, srvStartTime, uuid);
--#endif
-+
-     memcpy(&tsp, tspHandle, sizeof(tsp));
-     if (!status) {
-         status = krb5int_ipc_stream_new (&stream);  /* Create a stream for the request data */
-@@ -77,9 +75,7 @@ void ccs_rpc_connect_reply(
- 
-     HANDLE  hEvent  = openThreadEvent(uuid, REPLY_SUFFIX);
-     DWORD*  p       = (DWORD*)(tspHandle);
--#if 0
--    cci_debug_printf("%s! msg#:%d SST:%ld uuid:%s", __FUNCTION__, rpcmsg, srvStartTime, uuid);
--#endif
-+
-     SetEvent(hEvent);
-     CloseHandle(hEvent);
-     }
-diff --git a/src/ccapi/lib/win/dllmain.cxx b/src/ccapi/lib/win/dllmain.cxx
-index 82cacad9c..aa5d00a65 100644
---- a/src/ccapi/lib/win/dllmain.cxx
-+++ b/src/ccapi/lib/win/dllmain.cxx
-@@ -163,17 +163,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL,     // DLL module handle
-             // using multiple DLLs that use this DLL.
-             //
-             WaitForSingleObject( hCCAPIv2Mutex, INFINITE );
--#if 0
--            bool process_teardown_workaround = false;
--            if (lpvReserved) {
--                Init::InitInfo info;
--                status = Init::Info(info);
--                if (status) break;
--                if (!info.isNT) process_teardown_workaround = true;
--            }
--            if (process_teardown_workaround)
--                break;
--#endif
-+
-             // return value is ignored, so we set status for debugging purposes
-             status = Client::Cleanup();
-             status = Init::Cleanup();
-diff --git a/src/ccapi/server/win/ccs_os_server.cpp b/src/ccapi/server/win/ccs_os_server.cpp
-index f84239491..7c5012039 100644
---- a/src/ccapi/server/win/ccs_os_server.cpp
-+++ b/src/ccapi/server/win/ccs_os_server.cpp
-@@ -245,10 +245,7 @@ cc_int32 ccs_os_server_listen_loop (int argc, const char *argv[]) {
- 
-             if (worklist_remove(&rpcmsg, &pipe, &buf, &serverStartTime)) {
-                 uuid = ccs_win_pipe_getUuid(pipe);
--#if 0
--                cci_debug_printf("%s: processing WorkItem msg:%ld pipeUUID:<%s> pipeHandle:0x%X SST:%ld",
--                    __FUNCTION__, rpcmsg, uuid, ccs_win_pipe_getHandle(pipe), serverStartTime);
--#endif
-+
-                 if (serverStartTime <= getMySST()) {
-                     switch (rpcmsg) {
-                         case CCMSG_CONNECT: {
-@@ -472,13 +469,6 @@ void    receiveLoop(void* rpcargs) {
-     }   // End receiveLoop
- 
- 
--#if 0
--
--    return status;
--}
--#endif
--
--
- 
- /* ------------------------------------------------------------------------ */
- /* The connection listener thread waits forever for a call to the CCAPI_CLIENT_<UUID>
-@@ -647,17 +637,6 @@ RPC_STATUS send_connection_reply(ccs_pipe_t in_pipe) {
-     return (status);
-     }
- 
--#if 0
--DWORD alloc_name(LPSTR* pname, LPSTR postfix) {
--    DWORD len = strlen(sessID) + 1 + strlen(postfix) + 1;
--
--    *pname = (LPSTR)malloc(len);
--    if (!*pname) return GetLastError();
--    _snprintf(*pname, len, "%s.%s", sessID, postfix);
--    return 0;
--    }
--#endif
--
- RPC_STATUS GetPeerName( RPC_BINDING_HANDLE hClient,
-                         LPTSTR pszClientName,
-                         int iMaxLen) {
-diff --git a/src/ccapi/server/win/ccs_request_proc.c b/src/ccapi/server/win/ccs_request_proc.c
-index 461c441ed..c0328ea7e 100644
---- a/src/ccapi/server/win/ccs_request_proc.c
-+++ b/src/ccapi/server/win/ccs_request_proc.c
-@@ -45,9 +45,7 @@ void ccs_rpc_request(
-     k5_ipc_stream   stream;
-     UINT64*         p       = (UINT64*)(tspHandle);
-     WIN_PIPE*       pipe    = NULL;
--#if 0
--    cci_debug_printf("%s rpcmsg:%d; UUID:<%s> SST:<%s>", __FUNCTION__, rpcmsg, pszUUID, serverStartTime);
--#endif
-+
-     status = (rpcmsg != CCMSG_REQUEST) && (rpcmsg != CCMSG_PING);
- 
-     if (!status) {
-@@ -72,9 +70,7 @@ void ccs_rpc_connect(
- 
-     UINT64*     p       = (UINT64*)(tspHandle);
-     WIN_PIPE*   pipe    = ccs_win_pipe_new(pszUUID, *p);
--#if 0
--    cci_debug_printf("%s; rpcmsg:%d; UUID: <%s>", __FUNCTION__, rpcmsg, pszUUID);
--#endif
-+
-     worklist_add(   rpcmsg,
-                     pipe,
-                     NULL,               /* No payload with connect request */
-@@ -89,9 +85,7 @@ CC_UINT32 ccs_authenticate(const CC_CHAR* name) {
-     PDWORD      pvalue  = 0;
-     CC_UINT32   result  = 0;
-     DWORD       status  = 0;
--#if 0
--    cci_debug_printf("%s ( %s )", __FUNCTION__, name);
--#endif
-+
-     hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, (LPSTR)name);
-     status  = !hMap;
- 
-diff --git a/src/ccapi/server/win/ccs_win_pipe.c b/src/ccapi/server/win/ccs_win_pipe.c
-index d23e4448e..99c667017 100644
---- a/src/ccapi/server/win/ccs_win_pipe.c
-+++ b/src/ccapi/server/win/ccs_win_pipe.c
-@@ -61,9 +61,7 @@ struct ccs_win_pipe_t* ccs_win_pipe_new (const char* uuid, const UINT64 h) {
-         out_pipe->uuid          = uuidCopy;
-         out_pipe->clientHandle  = h;
-         }
--#if 0
--    cci_debug_printf("0x%X = %s(%s, 0x%X)", out_pipe, __FUNCTION__, uuid, h);
--#endif
-+
-     return out_pipe;
-     }
- 
-diff --git a/src/ccapi/test/pingtest.c b/src/ccapi/test/pingtest.c
-index d44839f71..0ffc15e7a 100644
---- a/src/ccapi/test/pingtest.c
-+++ b/src/ccapi/test/pingtest.c
-@@ -74,12 +74,6 @@ int main(   int argc, char *argv[]) {
- 
-     if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
- 
--//    send_test("krbcc.229026.0.ep");
--
--#if 0
--    err = cc_initialize(&context, ccapi_version_7, NULL, NULL);
--#endif
--
-     if (!err) {
-         err = cci_os_ipc_thread_init();
-         }
-diff --git a/src/clients/ksu/authorization.c b/src/clients/ksu/authorization.c
-index 90aafbd75..891921870 100644
---- a/src/clients/ksu/authorization.c
-+++ b/src/clients/ksu/authorization.c
-@@ -123,23 +123,6 @@ krb5_error_code krb5_authorization(context, principal, luser,
-                 "In krb5_authorization: if auth files exist -> can access\n");
-     }
- 
--#if 0
--    if (cmd){
--        if(k5users_flag){
--            return 0; /* if  kusers does not exist -> done */
--        }else{
--            if(retval = k5users_lookup(users_fp,princname,
--                                       cmd,&retbool,out_fcmd)){
--                auth_cleanup(users_fp, login_fp, princname);
--                return retval;
--            }else{
--                *ok =retbool;
--                return retval;
--            }
--        }
--    }
--#endif
--
-     /* if either file exists,
-        first see if the principal is in the login in file,
-        if it's not there check the k5users file */
-diff --git a/src/config/win-post.in b/src/config/win-post.in
-index 6535c1ba5..3f43bda77 100644
---- a/src/config/win-post.in
-+++ b/src/config/win-post.in
-@@ -121,14 +121,6 @@ clean-windows-files:
- !else
- 	@if exist $(OUTPRE3)$(DIRNUL) deltree /y $(OUTPRE3)
- !endif
--!if 0
--	$(RM) .\$(OUTPRE)*.obj .\$(OUTPRE)*.res
--	$(RM) .\$(OUTPRE)*.exe .\$(OUTPRE)*.dll
--	$(RM) .\$(OUTPRE)*.lib .\$(OUTPRE)*.pdb
--	$(RM) .\$(OUTPRE)*.exp .\$(OUTPRE)*.map
--	$(RM) .\$(OUTPRE)*.idb .\$(OUTPRE)*.ilk
--	$(RM) .\$(OUTPRE)*.manifest
--!endif
- 
- # Dependencies
- !if exist($(srcdir)/deps)
-diff --git a/src/include/gssrpc/auth.h b/src/include/gssrpc/auth.h
-index 0f653fcc7..8576c5142 100644
---- a/src/include/gssrpc/auth.h
-+++ b/src/include/gssrpc/auth.h
-@@ -75,12 +75,6 @@ enum auth_stat {
- };
- 
- union des_block {
--#if 0 /* XXX nothing uses this, anyway */
--	struct {
--		uint32_t high;
--		uint32_t low;
--	} key;
--#endif
- 	char c[8];
- };
- typedef union des_block des_block;
-@@ -207,15 +201,6 @@ extern bool_t xdr_opaque_auth(XDR *, struct opaque_auth *);
- #define AUTH_GSSAPI	300001		/* GSS-API style */
- #define RPCSEC_GSS	6		/* RPCSEC_GSS */
- 
--#if 0
--/*
-- * BACKWARDS COMPATIBILIY!  OpenV*Secure 1.0 had AUTH_GSSAPI == 4.  We
-- * need to accept this value until 1.0 is dead.
-- */
--/* This conflicts with AUTH_KERB (Solaris). */
--#define AUTH_GSSAPI_COMPAT		4
--#endif
--
- GSSRPC__END_DECLS
- 
- #endif /* !defined(GSSRPC_AUTH_H) */
-diff --git a/src/include/gssrpc/rename.h b/src/include/gssrpc/rename.h
-index 669a0580c..df37e95b7 100644
---- a/src/include/gssrpc/rename.h
-+++ b/src/include/gssrpc/rename.h
-@@ -50,10 +50,7 @@
-  * External names in the RPC API not beginning with "_" get renamed
-  * with the prefix "gssrpc_" via #define, e.g., "foo" -> "gssrpc_foo".
-  * External names in the RPC API beginning with "_" get textually
-- * rewritten, with "#if 0"-disabled #defines mapping them back to
-- * their original forms, e.g., "_foo" is rewrittten to "gssrpc__foo"
-- * in the original files, with an unused "#define gssrpc__foo _foo"
-- * here.
-+ * rewritten.
-  */
- 
- #ifndef GSSRPC_RENAME_H
-@@ -72,10 +69,6 @@
- #define authdes_create		gssrpc_authdes_create
- #define xdr_opaque_auth		gssrpc_xdr_opaque_auth
- 
--#if 0
--#define gssrpc__null_auth	_null_auth
--#endif
--
- /* auth_gss.c */
- 
- #define auth_debug_gss		gssrpc_auth_debug_gss
-@@ -181,10 +174,6 @@
- #define callrpc			gssrpc_callrpc
- #define getrpcport		gssrpc_getrpcport
- 
--#if 0
--#define gssrpc__rpc_getdtablesize	_rpc_getdtablesize
--#endif
--
- /* rpc_msg.h */
- 
- #define xdr_callmsg		gssrpc_xdr_callmsg
-@@ -193,10 +182,6 @@
- #define xdr_accepted_reply	gssrpc_xdr_accepted_reply
- #define xdr_rejected_reply	gssrpc_xdr_rejected_reply
- 
--#if 0
--#define gssrpc__seterr_reply	_seterr_reply
--#endif
--
- /* svc.h */
- 
- #define svc_register		gssrpc_svc_register
-@@ -244,15 +229,6 @@
- #define svcauth_gss_set_svc_name	gssrpc_svcauth_gss_set_svc_name
- #define svcauth_gss_get_principal	gssrpc_svcauth_gss_get_principal
- 
--#if 0
--#define gssrpc__authenticate	_authenticate
--#define gssrpc__svcauth_none	_svcauth_none
--#define gssrpc__svcauth_unix	_svcauth_unix
--#define gssrpc__svcauth_short	_svcauth_short
--#define gssrpc__svcauth_gssapi	_svcauth_gssapi
--#define gssrpc__svcauth_gss	_svcauth_gss
--#endif
--
- /* svc_auth_gss.c */
- 
- #define svc_debug_gss		gssrpc_svc_debug_gss
-diff --git a/src/include/gssrpc/rpc.h b/src/include/gssrpc/rpc.h
-index 2d94a7fe9..78727c49d 100644
---- a/src/include/gssrpc/rpc.h
-+++ b/src/include/gssrpc/rpc.h
-@@ -55,36 +55,11 @@
- #include <gssrpc/rpc_msg.h>	/* protocol for rpc messages */
- #include <gssrpc/auth_unix.h>	/* protocol for unix style cred */
- #include <gssrpc/auth_gss.h>	/* RPCSEC_GSS */
--/*
-- *  Uncomment-out the next line if you are building the rpc library with
-- *  DES Authentication (see the README file in the secure_rpc/ directory).
-- */
--#if 0
--#include <gssrpc/auth_des.h>	protocol for des style cred
--#endif
- 
- /* Server side only remote procedure callee */
- #include <gssrpc/svc_auth.h>	/* service side authenticator */
- #include <gssrpc/svc.h>		/* service manager and multiplexer */
- 
--/*
-- * Punt the rpc/netdb.h everywhere because it just makes things much more
-- * difficult.  We don't use the *rpcent functions anyway.
-- */
--#if 0
--/*
-- * COMMENT OUT THE NEXT INCLUDE IF RUNNING ON SUN OS OR ON A VERSION
-- * OF UNIX BASED ON NFSSRC.  These systems will already have the structures
-- * defined by <rpc/netdb.h> included in <netdb.h>.
-- */
--/* routines for parsing /etc/rpc */
--#if 0 /* netdb.h already included in rpc/types.h */
--#include <netdb.h>
--#endif
--
--#include <gssrpc/netdb.h>	/* structures and routines to parse /etc/rpc */
--#endif
--
- /*
-  * get the local host's IP address without consulting
-  * name service library functions
-diff --git a/src/include/gssrpc/types.hin b/src/include/gssrpc/types.hin
-index 022ab4fa9..4c4120c6f 100644
---- a/src/include/gssrpc/types.hin
-+++ b/src/include/gssrpc/types.hin
-@@ -116,13 +116,6 @@ typedef int32_t		rpc_inline_t;
- #define mem_alloc(bsize)	malloc(bsize)
- #define mem_free(ptr, bsize)	free(ptr)
- 
--#if 0
--#include <netdb.h> /* XXX This should not have to be here.
--		    * I got sick of seeing the warnings for MAXHOSTNAMELEN
--		    * and the two values were different. -- shanzer
--		    */
--#endif
--
- #ifndef INADDR_LOOPBACK
- #define       INADDR_LOOPBACK         (uint32_t)0x7F000001
- #endif
-diff --git a/src/include/k5-platform.h b/src/include/k5-platform.h
-index 763408a09..3368c7193 100644
---- a/src/include/k5-platform.h
-+++ b/src/include/k5-platform.h
-@@ -526,15 +526,11 @@ typedef struct { int error; unsigned char did_run; } k5_init_t;
- # endif
- #elif TARGET_OS_MAC
- # include <architecture/byte_order.h>
--# if 0 /* This causes compiler warnings.  */
--#  define SWAP16                OSSwapInt16
--# else
--#  define SWAP16                k5_swap16
-+# define SWAP16                k5_swap16
- static inline unsigned int k5_swap16 (unsigned int x) {
-     x &= 0xffff;
-     return (x >> 8) | ((x & 0xff) << 8);
- }
--# endif
- # define SWAP32                 OSSwapInt32
- # define SWAP64                 OSSwapInt64
- #elif defined(HAVE_SYS_BSWAP_H)
-@@ -848,25 +844,6 @@ k5_ntohll (uint64_t val)
-    business.  Probably most callers won't check the return status
-    anyways.  */
- 
--#if 0
--static inline void
--set_cloexec_fd(int fd)
--{
--#if defined(F_SETFD)
--# ifdef FD_CLOEXEC
--    (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
--# else
--    (void)fcntl(fd, F_SETFD, 1);
--# endif
--#endif
--}
--
--static inline void
--set_cloexec_file(FILE *f)
--{
--    return set_cloexec_fd(fileno(f));
--}
--#else
- /* Macros make the Sun compiler happier, and all variants of this do a
-    single evaluation of the argument, and fcntl and fileno should
-    produce reasonable error messages on type mismatches, on any system
-@@ -881,9 +858,6 @@ set_cloexec_file(FILE *f)
- # define set_cloexec_fd(FD)     ((void)(FD))
- #endif
- #define set_cloexec_file(F)     set_cloexec_fd(fileno(F))
--#endif
--
--
- 
- /* Since the original ANSI C spec left it undefined whether or
-    how you could copy around a va_list, C 99 added va_copy.
-diff --git a/src/kadmin/dbutil/kdb5_util.c b/src/kadmin/dbutil/kdb5_util.c
-index 000b5595c..4ff1cdf38 100644
---- a/src/kadmin/dbutil/kdb5_util.c
-+++ b/src/kadmin/dbutil/kdb5_util.c
-@@ -358,44 +358,6 @@ int main(argc, argv)
-     return exit_status;
- }
- 
--#if 0
--/*
-- * This function is no longer used in kdb5_util (and it would no
-- * longer work, anyway).
-- */
--void set_dbname(argc, argv)
--    int argc;
--    char *argv[];
--{
--    krb5_error_code retval;
--
--    if (argc < 3) {
--        com_err(argv[0], 0, _("Too few arguments"));
--        com_err(progname, 0, _("Usage: %s dbpathname realmname"), argv[0]);
--        exit_status++;
--        return;
--    }
--    if (dbactive) {
--        if ((retval = krb5_db_fini(util_context)) && retval!= KRB5_KDB_DBNOTINITED) {
--            com_err(progname, retval, _("while closing previous database"));
--            exit_status++;
--            return;
--        }
--        if (valid_master_key) {
--            krb5_free_keyblock_contents(util_context, &master_keyblock);
--            master_keyblock.contents = NULL;
--            valid_master_key = 0;
--        }
--        krb5_free_principal(util_context, master_princ);
--        free(mkey_fullname);
--        dbactive = FALSE;
--    }
--
--    (void) set_dbname_help(progname, argv[1]);
--    return;
--}
--#endif
--
- /*
-  * open_db_and_mkey: Opens the KDC and policy database, and sets the
-  * global master_* variables.  Sets dbactive to TRUE if the databases
-diff --git a/src/kadmin/server/ipropd_svc.c b/src/kadmin/server/ipropd_svc.c
-index e6e190136..3228687c7 100644
---- a/src/kadmin/server/ipropd_svc.c
-+++ b/src/kadmin/server/ipropd_svc.c
-@@ -621,32 +621,3 @@ krb5_iprop_prog_1(struct svc_req *rqstp,
-     }
- 
- }
--
--#if 0
--/*
-- * Get the host base service name for the kiprop principal. Returns
-- * KADM5_OK on success. Caller must free the storage allocated for
-- * host_service_name.
-- */
--kadm5_ret_t
--kiprop_get_adm_host_srv_name(krb5_context context,
--			     const char *realm,
--			     char **host_service_name)
--{
--    kadm5_ret_t ret;
--    char *name;
--    char *host;
--
--    if (ret = kadm5_get_master(context, realm, &host))
--	return (ret);
--
--    if (asprintf(&name, "%s@%s", KIPROP_SVC_NAME, host) < 0) {
--	free(host);
--	return (ENOMEM);
--    }
--    free(host);
--    *host_service_name = name;
--
--    return (KADM5_OK);
--}
--#endif
-diff --git a/src/kdc/kdc_log.c b/src/kdc/kdc_log.c
-index 7e8733980..4eec50373 100644
---- a/src/kdc/kdc_log.c
-+++ b/src/kdc/kdc_log.c
-@@ -94,14 +94,6 @@ log_as_req(krb5_context context,
-     krb5_db_audit_as_req(context, request,
-                          local_addr->address, remote_addr->address,
-                          client, server, authtime, errcode);
--#if 0
--    /* Sun (OpenSolaris) version would probably something like this.
--       The client and server names passed can be null, unlike in the
--       logging routines used above.  Note that a struct in_addr is
--       used, but the real address could be an IPv6 address.  */
--    audit_krb5kdc_as_req(some in_addr *, (in_port_t)remote_addr->port, 0,
--                         cname, sname, errcode);
--#endif
- }
- 
- /*
-diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
-index 86b9e2991..811c16368 100644
---- a/src/kdc/kdc_preauth.c
-+++ b/src/kdc/kdc_preauth.c
-@@ -712,19 +712,6 @@ const char *missing_required_preauth(krb5_db_entry *client,
-                                      krb5_db_entry *server,
-                                      krb5_enc_tkt_part *enc_tkt_reply)
- {
--#if 0
--    /*
--     * If this is the pwchange service, and the pre-auth bit is set,
--     * allow it even if the HW preauth would normally be required.
--     *
--     * Sandia national labs wanted this for some strange reason... we
--     * leave it disabled normally.
--     */
--    if (isflagset(server->attributes, KRB5_KDB_PWCHANGE_SERVICE) &&
--        isflagset(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH))
--        return 0;
--#endif
--
- #ifdef DEBUG
-     krb5_klog_syslog (
-         LOG_DEBUG,
-diff --git a/src/lib/apputils/net-server.c b/src/lib/apputils/net-server.c
-index a40da927e..54ee4c5c5 100644
---- a/src/lib/apputils/net-server.c
-+++ b/src/lib/apputils/net-server.c
-@@ -1060,17 +1060,6 @@ process_packet(verto_ctx *ctx, verto_ev *ev)
-         return;
-     }
- 
--#if 0
--    if (state->daddr_len > 0) {
--        char addrbuf[100];
--        if (getnameinfo(ss2sa(&state->daddr), state->daddr_len,
--                        addrbuf, sizeof(addrbuf),
--                        0, 0, NI_NUMERICHOST))
--            strlcpy(addrbuf, "?", sizeof(addrbuf));
--        com_err(conn->prog, 0, _("pktinfo says local addr is %s"), addrbuf);
--    }
--#endif
--
-     if (state->daddr_len == 0 && conn->type == CONN_UDP) {
-         /*
-          * An address couldn't be obtained, so the PKTINFO option probably
-@@ -1116,11 +1105,6 @@ kill_lru_tcp_or_rpc_connection(void *handle, verto_ev *newev)
-             continue;
-         if (c->type != CONN_TCP && c->type != CONN_RPC)
-             continue;
--#if 0
--        krb5_klog_syslog(LOG_INFO, "fd %d started at %ld",
--                         verto_get_fd(oldest_ev),
--                         c->start_time);
--#endif
-         if (oldest_c == NULL
-             || oldest_c->start_time > c->start_time) {
-             oldest_ev = ev;
-@@ -1186,10 +1170,6 @@ accept_tcp_connection(verto_ctx *ctx, verto_ev *ev)
-             strlcpy(p, tmpbuf, end - p);
-         }
-     }
--#if 0
--    krb5_klog_syslog(LOG_INFO, "accepted TCP connection on socket %d from %s",
--                     s, newconn->addrbuf);
--#endif
- 
-     newconn->addr_s = addr_s;
-     newconn->addrlen = addrlen;
-@@ -1481,9 +1461,6 @@ accept_rpc_connection(verto_ctx *ctx, verto_ev *ev)
-         newconn = verto_get_private(newev);
- 
-         set_cloexec_fd(s);
--#if 0
--        setnbio(s), setnolinger(s), setkeepalive(s);
--#endif
- 
-         if (getpeername(s, addr, &addrlen) ||
-             getnameinfo(addr, addrlen,
-@@ -1503,10 +1480,6 @@ accept_rpc_connection(verto_ctx *ctx, verto_ev *ev)
-                 strlcpy(p, tmpbuf, end - p);
-             }
-         }
--#if 0
--        krb5_klog_syslog(LOG_INFO, _("accepted RPC connection on socket %d "
--                                     "from %s"), s, newconn->addrbuf);
--#endif
- 
-         newconn->addr_s = addr_s;
-         newconn->addrlen = addrlen;
-diff --git a/src/lib/crypto/builtin/des/destest.c b/src/lib/crypto/builtin/des/destest.c
-index dd2f68ec4..0d92b365b 100644
---- a/src/lib/crypto/builtin/des/destest.c
-+++ b/src/lib/crypto/builtin/des/destest.c
-@@ -67,9 +67,6 @@ main(argc, argv)
-     char *argv[];
- {
-     char block1[17], block2[17], block3[17];
--#if 0
--    mit_des_cblock key, input, output, output2;
--#else
-     /* Force tests of unaligned accesses.  */
-     union { unsigned char c[8*4+3]; long l; } u;
-     unsigned char *ioblocks = u.c;
-@@ -77,7 +74,6 @@ main(argc, argv)
-     unsigned char *output = ioblocks+10;
-     unsigned char *output2 = ioblocks+19;
-     unsigned char *key = ioblocks+27;
--#endif
-     mit_des_key_schedule sched;
-     int num = 0;
-     int retval;
-diff --git a/src/lib/crypto/builtin/des/t_verify.c b/src/lib/crypto/builtin/des/t_verify.c
-index 1f3239fed..f4332f5c0 100644
---- a/src/lib/crypto/builtin/des/t_verify.c
-+++ b/src/lib/crypto/builtin/des/t_verify.c
-@@ -334,30 +334,6 @@ main(argc,argv)
-     exit(0);
- }
- 
--#if 0
--void
--flip(array)
--    char *array;
--{
--    register int old,new,i,j;
--    /* flips the bit order within each byte from 0 lsb to 0 msb */
--    for (i = 0; i<=7; i++) {
--        old = *array;
--        new = 0;
--        for (j = 0; j<=7; j++) {
--            if (old & 01)
--                new = new | 01;
--            if (j < 7) {
--                old = old >> 1;
--                new = new << 1;
--            }
--        }
--        *array = new;
--        array++;
--    }
--}
--#endif
--
- static void
- do_encrypt(in,out)
-     unsigned char *in;
-diff --git a/src/lib/crypto/builtin/pbkdf2.c b/src/lib/crypto/builtin/pbkdf2.c
-index d36b32e7e..8905f2671 100644
---- a/src/lib/crypto/builtin/pbkdf2.c
-+++ b/src/lib/crypto/builtin/pbkdf2.c
-@@ -102,11 +102,6 @@ F(char *output, char *u_tmp1, char *u_tmp2,
-     krb5_data out;
-     krb5_error_code err;
- 
--#if 0
--    printf("F(i=%d, count=%lu, pass=%d:%s)\n", i, count,
--           pass->length, pass->data);
--#endif
--
-     /* Compute U_1.  */
-     store_32_be(i, ibytes);
- 
-@@ -114,45 +109,25 @@ F(char *output, char *u_tmp1, char *u_tmp2,
-     memcpy(u_tmp2 + salt->length, ibytes, 4);
-     sdata = make_data(u_tmp2, salt->length + 4);
- 
--#if 0
--    printd("initial salt", &sdata);
--#endif
--
-     out = make_data(u_tmp1, hlen);
- 
--#if 0
--    printf("F: computing hmac #1 (U_1) with %s\n", pdata.contents);
--#endif
-     err = hmac(hash, pass, &sdata, &out);
-     if (err)
-         return err;
--#if 0
--    printd("F: prf return value", &out);
--#endif
-+
-     memcpy(output, u_tmp1, hlen);
- 
-     /* Compute U_2, .. U_c.  */
-     sdata.length = hlen;
-     for (j = 2; j <= count; j++) {
--#if 0
--        printf("F: computing hmac #%d (U_%d)\n", j, j);
--#endif
-         memcpy(u_tmp2, u_tmp1, hlen);
-         err = hmac(hash, pass, &sdata, &out);
-         if (err)
-             return err;
--#if 0
--        printd("F: prf return value", &out);
--#endif
-+
-         /* And xor them together.  */
-         for (k = 0; k < hlen; k++)
-             output[k] ^= u_tmp1[k];
--#if 0
--        printf("F: xor result:\n");
--        for (k = 0; k < hlen; k++)
--            printf(" %02x", 0xff & output[k]);
--        printf("\n");
--#endif
-     }
-     return 0;
- }
-@@ -185,9 +160,6 @@ pbkdf2(const struct krb5_hash_provider *hash, krb5_keyblock *pass,
- 
-     /* Step 3.  */
-     for (i = 1; i <= l; i++) {
--#if 0
--        int j;
--#endif
-         krb5_error_code err;
-         char *out;
- 
-@@ -205,12 +177,6 @@ pbkdf2(const struct krb5_hash_provider *hash, krb5_keyblock *pass,
-             memcpy(output->data + (i-1) * hlen, utmp3,
-                    output->length - (i-1) * hlen);
- 
--#if 0
--        printf("after F(%d), @%p:\n", i, output->data);
--        for (j = (i-1) * hlen; j < i * hlen; j++)
--            printf(" %02x", 0xff & output->data[j]);
--        printf ("\n");
--#endif
-     }
-     free(utmp1);
-     free(utmp2);
-diff --git a/src/lib/crypto/builtin/sha1/t_shs.c b/src/lib/crypto/builtin/sha1/t_shs.c
-index 08157b662..c1d18f557 100644
---- a/src/lib/crypto/builtin/sha1/t_shs.c
-+++ b/src/lib/crypto/builtin/sha1/t_shs.c
-@@ -59,10 +59,6 @@ main()
- {
-     SHS_INFO shsInfo;
-     unsigned int i;
--#if 0
--    time_t secondCount;
--    SHS_BYTE data[ 200 ];
--#endif
- 
-     /* Make sure we've got the endianness set right.  If the machine is
-        big-endian (up to 64 bits) the following value will be signed,
-@@ -120,17 +116,6 @@ main()
-     puts( "passed, result= 3232AFFA48628A26653B5AAA44541FD90D690603" );
- #endif /* NEW_SHS */
- 
--#if 0
--    printf( "\nTesting speed for 100MB data... " );
--    shsInit( &shsInfo );
--    secondCount = time( NULL );
--    for( i = 0; i < 500000U; i++ )
--        shsUpdate( &shsInfo, data, 200 );
--    secondCount = time( NULL ) - secondCount;
--    printf( "done.  Time = %ld seconds, %ld kbytes/second.\n", \
--            secondCount, 100500L / secondCount );
--#endif
--
-     puts( "\nAll SHS tests passed" );
-     exit( 0 );
- }
-diff --git a/src/lib/crypto/crypto_tests/t_cksums.c b/src/lib/crypto/crypto_tests/t_cksums.c
-index 4b5406e67..5afc90ed8 100644
---- a/src/lib/crypto/crypto_tests/t_cksums.c
-+++ b/src/lib/crypto/crypto_tests/t_cksums.c
-@@ -175,15 +175,11 @@ printhex(const char *head, void *data, size_t len)
- 
-     printf("%s", head);
-     for (i = 0; i < len; i++) {
--#if 0                           /* For convenience when updating test cases. */
--        printf("\\x%02X", ((unsigned char*)data)[i]);
--#else
-         printf("%02X", ((unsigned char*)data)[i]);
-         if (i % 16 == 15 && i + 1 < len)
-             printf("\n%*s", (int)strlen(head), "");
-         else if (i + 1 < len)
-             printf(" ");
--#endif
-     }
-     printf("\n");
- }
-diff --git a/src/lib/crypto/crypto_tests/t_crc.c b/src/lib/crypto/crypto_tests/t_crc.c
-index 1a35cfba5..8cd1d36cb 100644
---- a/src/lib/crypto/crypto_tests/t_crc.c
-+++ b/src/lib/crypto/crypto_tests/t_crc.c
-@@ -107,41 +107,9 @@ struct crc_trial trials[] = {
- 
- #define NTRIALS (sizeof(trials) / sizeof(trials[0]))
- 
--#if 0
--static void
--timetest(unsigned int nblk, unsigned int blksiz)
--{
--    char *block;
--    unsigned int i;
--    struct tms before, after;
--    unsigned long cksum;
- 
--    block = malloc(blksiz * nblk);
--    if (block == NULL)
--        exit(1);
--    for (i = 0; i < blksiz * nblk; i++)
--        block[i] = i % 256;
--    times(&before);
--    for (i = 0; i < nblk; i++) {
--        cksum = 0;
--        mit_crc32(block + i * blksiz, blksiz, &cksum);
--    }
--
--    times(&after);
--    printf("shift-8 implementation, %d blocks of %d bytes:\n",
--           nblk, blksiz);
--    printf("\tu=%ld s=%ld cu=%ld cs=%ld\n",
--           (long)(after.tms_utime - before.tms_utime),
--           (long)(after.tms_stime - before.tms_stime),
--           (long)(after.tms_cutime - before.tms_cutime),
--           (long)(after.tms_cstime - before.tms_cstime));
--
--    free(block);
--}
--#endif
--
--static void
--verify(void)
-+int
-+main(void)
- {
-     unsigned int i;
-     struct crc_trial trial;
-@@ -176,14 +144,5 @@ verify(void)
-                (trial.sum == cksum) ? "OK" : "***BAD***",
-                typestr, trial.data, cksum);
-     }
--}
--
--int
--main(void)
--{
--#if 0
--    timetest(64*1024, 1024);
--#endif
--    verify();
-     exit(0);
- }
-diff --git a/src/lib/crypto/crypto_tests/t_cts.c b/src/lib/crypto/crypto_tests/t_cts.c
-index 2b022b4ac..fe505169f 100644
---- a/src/lib/crypto/crypto_tests/t_cts.c
-+++ b/src/lib/crypto/crypto_tests/t_cts.c
-@@ -44,37 +44,10 @@
- 
- const char *whoami;
- 
--#if 0
--static void printhex (size_t len, const char *p)
--{
--    while (len--)
--        printf ("%02x", 0xff & *p++);
--}
--
--static void printstringhex (const char *p) { printhex (strlen (p), p); }
--
--static void printdata (krb5_data *d) { printhex (d->length, d->data); }
--
--static void printkey (krb5_keyblock *k) { printhex (k->length, k->contents); }
--#endif
--
--
- #define JURISIC "Juri\305\241i\304\207" /* hi Miro */
- #define ESZETT "\303\237"
- #define GCLEF  "\360\235\204\236" /* outside BMP, woo hoo!  */
- 
--#if 0
--static void
--check_error (int r, int line) {
--    if (r != 0) {
--        fprintf (stderr, "%s:%d: %s\n", __FILE__, line,
--                 error_message (r));
--        exit (1);
--    }
--}
--#define CHECK check_error(r, __LINE__)
--#endif
--
- static void printd (const char *descr, krb5_data *d) {
-     unsigned int i, j;
-     const int r = 16;
-diff --git a/src/lib/crypto/crypto_tests/t_decrypt.c b/src/lib/crypto/crypto_tests/t_decrypt.c
-index 1dbc4dd1b..4ae0256cc 100644
---- a/src/lib/crypto/crypto_tests/t_decrypt.c
-+++ b/src/lib/crypto/crypto_tests/t_decrypt.c
-@@ -658,15 +658,11 @@ printhex(const char *head, void *data, size_t len)
- 
-     printf("%s", head);
-     for (i = 0; i < len; i++) {
--#if 0                           /* For convenience when updating test cases. */
--        printf("\\x%02X", ((unsigned char*)data)[i]);
--#else
-         printf("%02X", ((unsigned char*)data)[i]);
-         if (i % 16 == 15 && i + 1 < len)
-             printf("\n%*s", (int)strlen(head), "");
-         else if (i + 1 < len)
-             printf(" ");
--#endif
-     }
-     printf("\n");
- }
-diff --git a/src/lib/crypto/crypto_tests/t_derive.c b/src/lib/crypto/crypto_tests/t_derive.c
-index 381ae4393..afbf7477f 100644
---- a/src/lib/crypto/crypto_tests/t_derive.c
-+++ b/src/lib/crypto/crypto_tests/t_derive.c
-@@ -273,15 +273,11 @@ printhex(const char *head, void *data, size_t len)
- 
-     printf("%s", head);
-     for (i = 0; i < len; i++) {
--#if 0                           /* For convenience when updating test cases. */
--        printf("\\x%02X", ((unsigned char*)data)[i]);
--#else
-         printf("%02X", ((unsigned char*)data)[i]);
-         if (i % 16 == 15 && i + 1 < len)
-             printf("\n%*s", (int)strlen(head), "");
-         else if (i + 1 < len)
-             printf(" ");
--#endif
-     }
-     printf("\n");
- }
-diff --git a/src/lib/crypto/crypto_tests/t_hmac.c b/src/lib/crypto/crypto_tests/t_hmac.c
-index 93d54828f..da359cb49 100644
---- a/src/lib/crypto/crypto_tests/t_hmac.c
-+++ b/src/lib/crypto/crypto_tests/t_hmac.c
-@@ -46,17 +46,6 @@ static void keyToData (krb5_keyblock *k, krb5_data *d) {
-     d->data = (char *) k->contents;
- }
- 
--#if 0
--static void check_error (int r, int line) {
--    if (r != 0) {
--        fprintf (stderr, "%s:%d: %s\n", __FILE__, line,
--                 error_message (r));
--        exit (1);
--    }
--}
--#define CHECK check_error(r, __LINE__)
--#endif
--
- static void printd (const char *descr, krb5_data *d) {
-     unsigned int i, j;
-     const int r = 16;
-diff --git a/src/lib/crypto/crypto_tests/t_str2key.c b/src/lib/crypto/crypto_tests/t_str2key.c
-index 7a7813874..27896e61e 100644
---- a/src/lib/crypto/crypto_tests/t_str2key.c
-+++ b/src/lib/crypto/crypto_tests/t_str2key.c
-@@ -719,15 +719,11 @@ printhex(const char *head, void *data, size_t len)
- 
-     printf("%s", head);
-     for (i = 0; i < len; i++) {
--#if 0                           /* For convenience when updating test cases. */
--        printf("\\x%02X", ((unsigned char*)data)[i]);
--#else
-         printf("%02X", ((unsigned char*)data)[i]);
-         if (i % 16 == 15 && i + 1 < len)
-             printf("\n%*s", (int)strlen(head), "");
-         else if (i + 1 < len)
-             printf(" ");
--#endif
-     }
-     printf("\n");
- }
-diff --git a/src/lib/crypto/crypto_tests/vectors.c b/src/lib/crypto/crypto_tests/vectors.c
-index 482d2de20..c1a765732 100644
---- a/src/lib/crypto/crypto_tests/vectors.c
-+++ b/src/lib/crypto/crypto_tests/vectors.c
-@@ -448,11 +448,6 @@ int main (int argc, char **argv)
- {
-     whoami = argv[0];
-     test_nfold ();
--#if 0
--    test_mit_des_s2k ();
--    test_des3_s2k ();
--    test_dr_dk ();
--#endif
-     test_pbkdf2();
-     return 0;
- }
-diff --git a/src/lib/crypto/krb/nfold.c b/src/lib/crypto/krb/nfold.c
-index ea02fddcf..75bceaecd 100644
---- a/src/lib/crypto/krb/nfold.c
-+++ b/src/lib/crypto/krb/nfold.c
-@@ -98,19 +98,9 @@ krb5int_nfold(unsigned int inbits, const unsigned char *in, unsigned int outbits
-         byte += out[i%outbits];
-         out[i%outbits] = byte&0xff;
- 
--#if 0
--        printf("msbit[%d] = %d\tbyte = %02x\tsum = %03x\n", i, msbit,
--               (((in[((inbits-1)-(msbit>>3))%inbits]<<8)|
--                 (in[((inbits)-(msbit>>3))%inbits]))
--                >>((msbit&7)+1))&0xff, byte);
--#endif
--
-         /* keep around the carry bit, if any */
-         byte >>= 8;
- 
--#if 0
--        printf("carry=%d\n", byte);
--#endif
-     }
- 
-     /* if there's a carry bit left over, add it back in */
-diff --git a/src/lib/gssapi/generic/util_set.c b/src/lib/gssapi/generic/util_set.c
-index 8866f525f..432a9ee0d 100644
---- a/src/lib/gssapi/generic/util_set.c
-+++ b/src/lib/gssapi/generic/util_set.c
-@@ -40,21 +40,6 @@ int g_set_init(g_set_elt *s)
-     return(0);
- }
- 
--#if 0
--int g_set_destroy(g_set_elt *s)
--{
--    g_set next;
--
--    while (*s) {
--        next = (*s)->next;
--        free(*s);
--        *s = next;
--    }
--
--    return(0);
--}
--#endif
--
- int g_set_entry_add(g_set_elt *s, void *key, void *value)
- {
-     g_set_elt first;
-diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c
-index 06967aa27..5baa6cecf 100644
---- a/src/lib/gssapi/krb5/accept_sec_context.c
-+++ b/src/lib/gssapi/krb5/accept_sec_context.c
-@@ -654,17 +654,6 @@ kg_accept_krb5(minor_status, context_handle,
- 
-     krb5_auth_con_getauthenticator(context, auth_context, &authdat);
- 
--#if 0
--    /* make sure the necessary parts of the authdat are present */
--
--    if ((authdat->authenticator->subkey == NULL) ||
--        (authdat->ticket->enc_part2 == NULL)) {
--        code = KG_NO_SUBKEY;
--        major_status = GSS_S_FAILURE;
--        goto fail;
--    }
--#endif
--
-     if (authdat->checksum == NULL) {
-         /*
-          * Some SMB client implementations use handcrafted GSSAPI code that
-diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
-index 43930dd61..1eaf2bffb 100644
---- a/src/lib/gssapi/krb5/gssapi_krb5.c
-+++ b/src/lib/gssapi/krb5/gssapi_krb5.c
-@@ -465,28 +465,12 @@ krb5_gss_inquire_cred_by_oid(OM_uint32 *minor_status,
-     return GSS_S_UNAVAILABLE;
- }
- 
--/*
-- * gss_set_sec_context_option() methods
-- * (Disabled until we have something to populate the array.)
-- */
--#if 0
--static struct {
--    gss_OID_desc oid;
--    OM_uint32 (*func)(OM_uint32 *, gss_ctx_id_t *, const gss_OID, const gss_buffer_t);
--} krb5_gss_set_sec_context_option_ops[] = {
--};
--#endif
--
- OM_uint32 KRB5_CALLCONV
- krb5_gss_set_sec_context_option (OM_uint32 *minor_status,
-                                  gss_ctx_id_t *context_handle,
-                                  const gss_OID desired_object,
-                                  const gss_buffer_t value)
- {
--#if 0
--    size_t i;
--#endif
--
-     if (minor_status == NULL)
-         return GSS_S_CALL_INACCESSIBLE_WRITE;
- 
-@@ -498,18 +482,6 @@ krb5_gss_set_sec_context_option (OM_uint32 *minor_status,
-     if (desired_object == GSS_C_NO_OID)
-         return GSS_S_CALL_INACCESSIBLE_READ;
- 
--#if 0
--    for (i = 0; i < sizeof(krb5_gss_set_sec_context_option_ops)/
--             sizeof(krb5_gss_set_sec_context_option_ops[0]); i++) {
--        if (g_OID_prefix_equal(desired_object, &krb5_gss_set_sec_context_option_ops[i].oid)) {
--            return (*krb5_gss_set_sec_context_option_ops[i].func)(minor_status,
--                                                                  context_handle,
--                                                                  desired_object,
--                                                                  value);
--        }
--    }
--#endif
--
-     *minor_status = EINVAL;
- 
-     return GSS_S_UNAVAILABLE;
-diff --git a/src/lib/gssapi/krb5/naming_exts.c b/src/lib/gssapi/krb5/naming_exts.c
-index 5f00efe34..41752d90b 100644
---- a/src/lib/gssapi/krb5/naming_exts.c
-+++ b/src/lib/gssapi/krb5/naming_exts.c
-@@ -664,13 +664,3 @@ cleanup:
- 
-     return kg_map_name_error(minor_status, code);
- }
--
--#if 0
--OM_uint32
--krb5_gss_display_name_ext(OM_uint32 *minor_status,
--                          gss_name_t name,
--                          gss_OID display_as_name_type,
--                          gss_buffer_t display_name)
--{
--}
--#endif
-diff --git a/src/lib/gssapi/mechglue/g_initialize.c b/src/lib/gssapi/mechglue/g_initialize.c
-index 9197666e1..0ad11c0b0 100644
---- a/src/lib/gssapi/mechglue/g_initialize.c
-+++ b/src/lib/gssapi/mechglue/g_initialize.c
-@@ -391,9 +391,6 @@ build_mechSet(void)
- 		g_mechSet.count = count;
- 	}
- 
--#if 0
--	g_mechSetTime = fileInfo.st_mtime;
--#endif
- 	k5_mutex_unlock(&g_mechSetLock);
- 	k5_mutex_unlock(&g_mechListLock);
- 
-@@ -916,10 +913,6 @@ loadInterMech(gss_mech_info minfo)
- 
- 	if (krb5int_open_plugin(minfo->uLibName, &dl, &errinfo) != 0 ||
- 	    errinfo.code != 0) {
--#if 0
--		(void) syslog(LOG_INFO, "libgss dlopen(%s): %s\n",
--				aMech->uLibName, dlerror());
--#endif
- 		return;
- 	}
- 
-@@ -959,12 +952,6 @@ loadInterMech(gss_mech_info minfo)
- 	dl = NULL;
- 
- cleanup:
--#if 0
--	if (aMech->mech == NULL) {
--		(void) syslog(LOG_INFO, "unable to initialize mechanism"
--				" library [%s]\n", aMech->uLibName);
--	}
--#endif
- 	if (dl != NULL)
- 		krb5int_close_plugin(dl);
- 	k5_clear_error(&errinfo);
-@@ -1161,10 +1148,6 @@ gssint_get_mechanism(gss_const_OID oid)
- 
- 	if (krb5int_open_plugin(aMech->uLibName, &dl, &errinfo) != 0 ||
- 	    errinfo.code != 0) {
--#if 0
--		(void) syslog(LOG_INFO, "libgss dlopen(%s): %s\n",
--				aMech->uLibName, dlerror());
--#endif
- 		k5_mutex_unlock(&g_mechListLock);
- 		return ((gss_mechanism)NULL);
- 	}
-@@ -1180,10 +1163,6 @@ gssint_get_mechanism(gss_const_OID oid)
- 	}
- 	if (aMech->mech == NULL) {
- 		(void) krb5int_close_plugin(dl);
--#if 0
--		(void) syslog(LOG_INFO, "unable to initialize mechanism"
--				" library [%s]\n", aMech->uLibName);
--#endif
- 		k5_mutex_unlock(&g_mechListLock);
- 		return ((gss_mechanism)NULL);
- 	}
-@@ -1503,10 +1482,6 @@ addConfigEntry(const char *oidStr, const char *oid, const char *sharedLib,
- 	oidBuf.length = strlen(oid);
- 	if (generic_gss_str_to_oid(&minor, &oidBuf, &mechOid)
- 		!= GSS_S_COMPLETE) {
--#if 0
--		(void) syslog(LOG_INFO, "invalid mechanism oid"
--				" [%s] in configuration file", oid);
--#endif
- 		return;
- 	}
- 
-diff --git a/src/lib/gssapi/mechglue/g_inq_cred.c b/src/lib/gssapi/mechglue/g_inq_cred.c
-index 911196264..cbe045ab9 100644
---- a/src/lib/gssapi/mechglue/g_inq_cred.c
-+++ b/src/lib/gssapi/mechglue/g_inq_cred.c
-@@ -198,11 +198,6 @@ gss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, name,
-     union_cred = (gss_union_cred_t) cred_handle;
-     mech_cred = gssint_get_mechanism_cred(union_cred, selected_mech);
- 
--#if 0
--    if (mech_cred == NULL)
--	return (GSS_S_DEFECTIVE_CREDENTIAL);
--#endif
--
-     public_mech = gssint_get_public_oid(selected_mech);
-     status = mech->gss_inquire_cred_by_mech(minor_status,
- 					    mech_cred, public_mech,
-diff --git a/src/lib/gssapi/mechglue/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h
-index 2b5145e07..2b00987e6 100644
---- a/src/lib/gssapi/mechglue/mglueP.h
-+++ b/src/lib/gssapi/mechglue/mglueP.h
-@@ -730,11 +730,6 @@ typedef struct gss_mech_config {
- /********************************************************/
- /* Internal mechglue routines */
- 
--#if 0
--int gssint_mechglue_init(void);
--void gssint_mechglue_fini(void);
--#endif
--
- OM_uint32 gssint_select_mech_type(OM_uint32 *minor, gss_const_OID in_oid,
- 				  gss_OID *selected_oid);
- gss_OID gssint_get_public_oid(gss_const_OID internal_oid);
-diff --git a/src/lib/kadm5/clnt/client_init.c b/src/lib/kadm5/clnt/client_init.c
-index 4350a9eb0..6f10db018 100644
---- a/src/lib/kadm5/clnt/client_init.c
-+++ b/src/lib/kadm5/clnt/client_init.c
-@@ -161,7 +161,6 @@ init_any(krb5_context context, char *client_name, enum init_type init_type,
-     generic_ret r = { 0, 0 };
- 
-     initialize_ovk_error_table();
--/*      initialize_adb_error_table(); */
-     initialize_ovku_error_table();
- 
-     if (! server_handle) {
-@@ -612,53 +611,8 @@ setup_gss(kadm5_server_handle_t handle, kadm5_config_params *params_in,
-     gssstat = gss_acquire_cred(&minor_stat, gss_client, 0,
-                                GSS_C_NULL_OID_SET, GSS_C_INITIATE,
-                                &handle->cred, NULL, NULL);
--    if (gssstat != GSS_S_COMPLETE) {
--#if 0 /* for debugging only */
--        {
--            OM_uint32 maj_status, min_status, message_context = 0;
--            gss_buffer_desc status_string;
--            do {
--                maj_status = gss_display_status(&min_status,
--                                                gssstat,
--                                                GSS_C_GSS_CODE,
--                                                GSS_C_NO_OID,
--                                                &message_context,
--                                                &status_string);
--                if (maj_status == GSS_S_COMPLETE) {
--                    fprintf(stderr, "MAJ: %.*s\n",
--                            (int) status_string.length,
--                            (char *)status_string.value);
--                    gss_release_buffer(&min_status, &status_string);
--                } else {
--                    fprintf(stderr,
--                            "MAJ? gss_display_status returns 0x%lx?!\n",
--                            (unsigned long) maj_status);
--                    message_context = 0;
--                }
--            } while (message_context != 0);
--            do {
--                maj_status = gss_display_status(&min_status,
--                                                minor_stat,
--                                                GSS_C_MECH_CODE,
--                                                GSS_C_NO_OID,
--                                                &message_context,
--                                                &status_string);
--                if (maj_status == GSS_S_COMPLETE) {
--                    fprintf(stderr, "MIN: %.*s\n",
--                            (int) status_string.length,
--                            (char *)status_string.value);
--                    gss_release_buffer(&min_status, &status_string);
--                } else {
--                    fprintf(stderr,
--                            "MIN? gss_display_status returns 0x%lx?!\n",
--                            (unsigned long) maj_status);
--                    message_context = 0;
--                }
--            } while (message_context != 0);
--        }
--#endif
-+    if (gssstat != GSS_S_COMPLETE)
-         goto error;
--    }
- 
-     /*
-      * Do actual creation of RPC auth handle.  Implements auth flavor
-diff --git a/src/lib/kadm5/srv/server_init.c b/src/lib/kadm5/srv/server_init.c
-index b3ae4ff5c..87a732292 100644
---- a/src/lib/kadm5/srv/server_init.c
-+++ b/src/lib/kadm5/srv/server_init.c
-@@ -186,7 +186,6 @@ kadm5_ret_t kadm5_init(krb5_context context, char *client_name, char *pass,
-     handle->context = context;
- 
-     initialize_ovk_error_table();
--/*     initialize_adb_error_table(); */
-     initialize_ovku_error_table();
- 
-     handle->magic_number = KADM5_SERVER_HANDLE_MAGIC;
-@@ -207,16 +206,6 @@ kadm5_ret_t kadm5_init(krb5_context context, char *client_name, char *pass,
-      */
-     memset(&params_local, 0, sizeof(params_local));
- 
--#if 0 /* Now that we look at krb5.conf as well as kdc.conf, we can
--         expect to see admin_server being set sometimes.  */
--#define ILLEGAL_PARAMS (KADM5_CONFIG_ADMIN_SERVER)
--    if (params_in && (params_in->mask & ILLEGAL_PARAMS)) {
--        free_db_args(handle);
--        free(handle);
--        return KADM5_BAD_SERVER_PARAMS;
--    }
--#endif
--
-     ret = kadm5_get_config_params(handle->context, 1, params_in,
-                                   &handle->params);
-     if (ret) {
-diff --git a/src/lib/kadm5/unit-test/setkey-test.c b/src/lib/kadm5/unit-test/setkey-test.c
-index 0431653bf..fa2392f81 100644
---- a/src/lib/kadm5/unit-test/setkey-test.c
-+++ b/src/lib/kadm5/unit-test/setkey-test.c
-@@ -35,15 +35,6 @@ krb5_keyblock *tests[] = {
-     test1, test2, test3, NULL
- };
- 
--#if 0
--int keyblocks_equal(krb5_keyblock *kb1, krb5_keyblock *kb2)
--{
--    return (kb1->enctype == kb2->enctype &&
--            kb1->length == kb2->length &&
--            memcmp(kb1->contents, kb2->contents, kb1->length) == 0);
--}
--#endif
--
- krb5_data tgtname = {
-     0,
-     KRB5_TGS_NAME_SIZE,
-diff --git a/src/lib/krb5/asn.1/ldap_key_seq.c b/src/lib/krb5/asn.1/ldap_key_seq.c
-index 74569d9e2..f0be2d6d9 100644
---- a/src/lib/krb5/asn.1/ldap_key_seq.c
-+++ b/src/lib/krb5/asn.1/ldap_key_seq.c
-@@ -96,9 +96,6 @@ no_salt(void *p)
- DEFOPTIONALTYPE(key_data_salt_if_present, is_salt_present, no_salt, krbsalt);
- DEFCTAGGEDTYPE(key_data_0, 0, key_data_salt_if_present);
- DEFCTAGGEDTYPE(key_data_1, 1, encryptionkey);
--#if 0 /* We don't support this field currently.  */
--DEFCTAGGEDTYPE(key_data_2, 2, s2kparams),
--#endif
- static const struct atype_info *key_data_fields[] = {
-     &k5_atype_key_data_0, &k5_atype_key_data_1
- };
-diff --git a/src/lib/krb5/ccache/ccapi/stdcc.c b/src/lib/krb5/ccache/ccapi/stdcc.c
-index 0256a0a5d..db69eebb4 100644
---- a/src/lib/krb5/ccache/ccapi/stdcc.c
-+++ b/src/lib/krb5/ccache/ccapi/stdcc.c
-@@ -1300,14 +1300,6 @@ krb5_error_code KRB5_CALLCONV  krb5_stdcc_initialize
-         return cc_err_xlate(err);
-     }
- 
--#if 0
--    /*
--     * Some implementations don't set the principal name
--     * correctly, so we force set it to the correct value.
--     */
--    err = cc_set_principal(gCntrlBlock, ccapi_data->NamedCache,
--                           CC_CRED_V5, cName);
--#endif
-     krb5_free_unparsed_name(context, cName);
-     cache_changed();
- 
-@@ -1432,54 +1424,6 @@ krb5_error_code KRB5_CALLCONV krb5_stdcc_next_cred
-  *
-  * - try to find a matching credential in the cache
-  */
--#if 0
--krb5_error_code KRB5_CALLCONV krb5_stdcc_retrieve
--(krb5_context context,
-- krb5_ccache id,
-- krb5_flags whichfields,
-- krb5_creds *mcreds,
-- krb5_creds *creds )
--{
--    krb5_error_code retval;
--    krb5_cc_cursor curs = NULL;
--    krb5_creds *fetchcreds;
--
--    if ((retval = stdcc_setup(context, NULL)))
--        return retval;
--
--    fetchcreds = (krb5_creds *)malloc(sizeof(krb5_creds));
--    if (fetchcreds == NULL) return KRB5_CC_NOMEM;
--
--    /* we're going to use the iterators */
--    krb5_stdcc_start_seq_get(context, id, &curs);
--
--    while (!krb5_stdcc_next_cred(context, id, &curs, fetchcreds)) {
--        /*
--         * look at each credential for a match
--         * use this match routine since it takes the
--         * whichfields and the API doesn't
--         */
--        if (stdccCredsMatch(context, fetchcreds,
--                            mcreds, whichfields)) {
--            /* we found it, copy and exit */
--            *creds = *fetchcreds;
--            krb5_stdcc_end_seq_get(context, id, &curs);
--            return 0;
--        }
--        /* free copy allocated by next_cred */
--        krb5_free_cred_contents(context, fetchcreds);
--    }
--
--    /* no luck, end get and exit */
--    krb5_stdcc_end_seq_get(context, id, &curs);
--
--    /* we're not using this anymore so we should get rid of it! */
--    free(fetchcreds);
--
--    return KRB5_CC_NOTFOUND;
--}
--#else
--
- krb5_error_code KRB5_CALLCONV
- krb5_stdcc_retrieve(context, id, whichfields, mcreds, creds)
-     krb5_context context;
-@@ -1492,8 +1436,6 @@ krb5_stdcc_retrieve(context, id, whichfields, mcreds, creds)
-                                        creds);
- }
- 
--#endif
--
- /*
-  *  end seq
-  *
-diff --git a/src/lib/krb5/ccache/ccapi/winccld.h b/src/lib/krb5/ccache/ccapi/winccld.h
-index 85017abbd..df34e3346 100644
---- a/src/lib/krb5/ccache/ccapi/winccld.h
-+++ b/src/lib/krb5/ccache/ccapi/winccld.h
-@@ -85,24 +85,10 @@ DECL_FUNC_PTR(cc_create);
- DECL_FUNC_PTR(cc_open);
- DECL_FUNC_PTR(cc_close);
- DECL_FUNC_PTR(cc_destroy);
--#if 0 /* Not used */
--#ifdef CC_API_VER2
--DECL_FUNC_PTR(cc_seq_fetch_NCs_begin);
--DECL_FUNC_PTR(cc_seq_fetch_NCs_next);
--DECL_FUNC_PTR(cc_seq_fetch_NCs_end);
--#else
--DECL_FUNC_PTR(cc_seq_fetch_NCs);
--#endif
--DECL_FUNC_PTR(cc_get_NC_info);
--DECL_FUNC_PTR(cc_free_NC_info);
--#endif
- DECL_FUNC_PTR(cc_get_name);
- DECL_FUNC_PTR(cc_set_principal);
- DECL_FUNC_PTR(cc_get_principal);
- DECL_FUNC_PTR(cc_get_cred_version);
--#if 0 /* Not used */
--DECL_FUNC_PTR(cc_lock_request);
--#endif
- DECL_FUNC_PTR(cc_store);
- DECL_FUNC_PTR(cc_remove_cred);
- #ifdef CC_API_VER2
-@@ -127,18 +113,10 @@ FUNC_INFO krbcc_fi[] = {
-     MAKE_FUNC_INFO(cc_open),
-     MAKE_FUNC_INFO(cc_close),
-     MAKE_FUNC_INFO(cc_destroy),
--#if 0 /* Not used */
--    MAKE_FUNC_INFO(cc_seq_fetch_NCs),
--    MAKE_FUNC_INFO(cc_get_NC_info),
--    MAKE_FUNC_INFO(cc_free_NC_info),
--#endif
-     MAKE_FUNC_INFO(cc_get_name),
-     MAKE_FUNC_INFO(cc_set_principal),
-     MAKE_FUNC_INFO(cc_get_principal),
-     MAKE_FUNC_INFO(cc_get_cred_version),
--#if 0 /* Not used */
--    MAKE_FUNC_INFO(cc_lock_request),
--#endif
-     MAKE_FUNC_INFO(cc_store),
-     MAKE_FUNC_INFO(cc_remove_cred),
- #ifdef CC_API_VER2
-@@ -166,24 +144,10 @@ FUNC_INFO krbcc_fi[] = {
- #define cc_open pcc_open
- #define cc_close pcc_close
- #define cc_destroy pcc_destroy
--#if 0 /* Not used */
--#ifdef CC_API_VER2
--#define cc_seq_fetch_NCs_begin pcc_seq_fetch_NCs_begin
--#define cc_seq_fetch_NCs_next pcc_seq_fetch_NCs_next
--#define cc_seq_fetch_NCs_end pcc_seq_fetch_NCs_end
--#else
--#define cc_seq_fetch_NCs pcc_seq_fetch_NCs
--#endif
--#define cc_get_NC_info pcc_get_NC_info
--#define cc_free_NC_info pcc_free_NC_info
--#endif /* End of Not used */
- #define cc_get_name pcc_get_name
- #define cc_set_principal pcc_set_principal
- #define cc_get_principal pcc_get_principal
- #define cc_get_cred_version pcc_get_cred_version
--#if 0 /* Not used */
--#define cc_lock_request pcc_lock_request
--#endif
- #define cc_store pcc_store
- #define cc_remove_cred pcc_remove_cred
- #ifdef CC_API_VER2
-diff --git a/src/lib/krb5/keytab/t_keytab.c b/src/lib/krb5/keytab/t_keytab.c
-index 80a94eafe..c845596d6 100644
---- a/src/lib/krb5/keytab/t_keytab.c
-+++ b/src/lib/krb5/keytab/t_keytab.c
-@@ -441,16 +441,3 @@ main(void)
-     return 0;
- 
- }
--
--
--#if 0
--/* remove and add are functions, so that they can return NOWRITE
--   if not a writable keytab */
--krb5_error_code KRB5_CALLCONV krb5_kt_remove_entry
--(krb5_context,
-- krb5_keytab,
-- krb5_keytab_entry * );
--
--
--
--#endif
-diff --git a/src/lib/krb5/krb/gc_via_tkt.c b/src/lib/krb5/krb/gc_via_tkt.c
-index 5b9bb9573..e7a3b01f8 100644
---- a/src/lib/krb5/krb/gc_via_tkt.c
-+++ b/src/lib/krb5/krb/gc_via_tkt.c
-@@ -131,17 +131,6 @@ check_reply_server(krb5_context context, krb5_flags kdcoptions,
-         /* Canonicalization not requested, and not a TGS referral. */
-         return KRB5_KDCREP_MODIFIED;
-     }
--#if 0
--    /*
--     * Is this check needed?  find_nxt_kdc() in gc_frm_kdc.c already
--     * effectively checks this.
--     */
--    if (krb5_realm_compare(context, in_cred->client, in_cred->server) &&
--        data_eq(*in_cred->server->data[1], *in_cred->client->realm)) {
--        /* Attempted to rewrite local TGS. */
--        return KRB5_KDCREP_MODIFIED;
--    }
--#endif
-     return 0;
- }
- 
-diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
-index 4246c5dd2..c90b2af87 100644
---- a/src/lib/krb5/krb/init_ctx.c
-+++ b/src/lib/krb5/krb/init_ctx.c
-@@ -232,13 +232,6 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
-     get_integer(ctx, KRB5_CONF_CLOCKSKEW, DEFAULT_CLOCKSKEW, &tmp);
-     ctx->clockskew = tmp;
- 
--#if 0
--    /* Default ticket lifetime is currently not supported */
--    profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS, "tkt_lifetime",
--                        0, 10 * 60 * 60, &tmp);
--    ctx->tkt_lifetime = tmp;
--#endif
--
-     /* DCE 1.1 and below only support CKSUMTYPE_RSA_MD4 (2)  */
-     /* DCE add kdc_req_checksum_type = 2 to krb5.conf */
-     get_integer(ctx, KRB5_CONF_KDC_REQ_CHECKSUM_TYPE, CKSUMTYPE_RSA_MD5,
-diff --git a/src/lib/krb5/krb/rd_req_dec.c b/src/lib/krb5/krb/rd_req_dec.c
-index 6defbdbf0..4cd429a11 100644
---- a/src/lib/krb5/krb/rd_req_dec.c
-+++ b/src/lib/krb5/krb/rd_req_dec.c
-@@ -441,30 +441,6 @@ decrypt_ticket(krb5_context context, const krb5_ap_req *req,
- #endif /* LEAN_CLIENT */
- }
- 
--#if 0
--#include <syslog.h>
--static void
--debug_log_authz_data(const char *which, krb5_authdata **a)
--{
--    if (a) {
--        syslog(LOG_ERR|LOG_DAEMON, "%s authz data:", which);
--        while (*a) {
--            syslog(LOG_ERR|LOG_DAEMON, "  ad_type:%d length:%d '%.*s'",
--                   (*a)->ad_type, (*a)->length, (*a)->length,
--                   (char *) (*a)->contents);
--            a++;
--        }
--        syslog(LOG_ERR|LOG_DAEMON, "  [end]");
--    } else
--        syslog(LOG_ERR|LOG_DAEMON, "no %s authz data", which);
--}
--#else
--static void
--debug_log_authz_data(const char *which, krb5_authdata **a)
--{
--}
--#endif
--
- static krb5_error_code
- rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context,
-                    const krb5_ap_req *req, krb5_const_principal server,
-@@ -759,8 +735,6 @@ rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context,
-                                     &((*auth_context)->key))))
-         goto cleanup;
- 
--    debug_log_authz_data("ticket", req->ticket->enc_part2->authorization_data);
--
-     /*
-      * If not AP_OPTS_MUTUAL_REQUIRED then and sequence numbers are used
-      * then the default sequence number is the one's complement of the
-@@ -855,10 +829,9 @@ decrypt_authenticator(krb5_context context, const krb5_ap_req *request,
-         free(scratch.data);}
- 
-     /*  now decode the decrypted stuff */
--    if (!(retval = decode_krb5_authenticator(&scratch, &local_auth))) {
-+    if (!(retval = decode_krb5_authenticator(&scratch, &local_auth)))
-         *authpp = local_auth;
--        debug_log_authz_data("authenticator", local_auth->authorization_data);
--    }
-+
-     clean_scratch();
-     return retval;
- }
-diff --git a/src/lib/krb5/krb/t_ser.c b/src/lib/krb5/krb/t_ser.c
-index 9cdf5e641..1d6cceaa2 100644
---- a/src/lib/krb5/krb/t_ser.c
-+++ b/src/lib/krb5/krb/t_ser.c
-@@ -151,10 +151,6 @@ ser_data(int verbose, char *msg, krb5_pointer ctx, krb5_magic dtype)
-                     krb5_encrypt_block *eblock;
- 
-                     eblock = (krb5_encrypt_block *) nctx;
--#if 0
--                    if (eblock->priv && eblock->priv_size)
--                        free(eblock->priv);
--#endif
-                     if (eblock->key)
-                         krb5_free_keyblock(ser_ctx, eblock->key);
-                     free(eblock);
-@@ -450,60 +446,6 @@ ser_rcache_test(krb5_context kcontext, int verbose)
-     return(kret);
- }
- 
--#if 0
--/*
-- * Serialize krb5_encrypt_block.
-- */
--static krb5_error_code
--ser_eblock_test(kcontext, verbose)
--    krb5_context        kcontext;
--    int                 verbose;
--{
--    krb5_error_code     kret;
--    krb5_encrypt_block  eblock;
--    krb5_keyblock       ukeyblock;
--    krb5_octet          keydata[8];
--
--    memset(&eblock, 0, sizeof(krb5_encrypt_block));
--    eblock.magic = KV5M_ENCRYPT_BLOCK;
--    krb5_use_enctype(kcontext, &eblock, DEFAULT_KDC_ENCTYPE);
--    if (!(kret = ser_data(verbose, "> NULL eblock",
--                          (krb5_pointer) &eblock, KV5M_ENCRYPT_BLOCK))) {
--#if 0
--        eblock.priv = (krb5_pointer) stuff;
--        eblock.priv_size = 8;
--#endif
--        if (!(kret = ser_data(verbose, "> eblock with private data",
--                              (krb5_pointer) &eblock,
--                              KV5M_ENCRYPT_BLOCK))) {
--            memset(&ukeyblock, 0, sizeof(ukeyblock));
--            memset(keydata, 0, sizeof(keydata));
--            ukeyblock.enctype = ENCTYPE_DES_CBC_MD5;
--            ukeyblock.length = sizeof(keydata);
--            ukeyblock.contents = keydata;
--            keydata[0] = 0xde;
--            keydata[1] = 0xad;
--            keydata[2] = 0xbe;
--            keydata[3] = 0xef;
--            keydata[4] = 0xfe;
--            keydata[5] = 0xed;
--            keydata[6] = 0xf0;
--            keydata[7] = 0xd;
--            eblock.key = &ukeyblock;
--            if (!(kret = ser_data(verbose, "> eblock with private key",
--                                  (krb5_pointer) &eblock,
--                                  KV5M_ENCRYPT_BLOCK))) {
--                if (verbose)
--                    printf("* eblock test succeeded\n");
--            }
--        }
--    }
--    if (kret)
--        printf("* eblock test failed\n");
--    return(kret);
--}
--#endif
--
- /*
-  * Serialize krb5_principal
-  */
-@@ -584,7 +526,7 @@ main(int argc, char **argv)
-     do_ptest = 1;
-     do_rtest = 1;
-     do_stest = 1;
--    while ((option = getopt(argc, argv, "acekprsxvACEKPRSX")) != -1) {
-+    while ((option = getopt(argc, argv, "acekprsxvACKPRSX")) != -1) {
-         switch (option) {
-         case 'a':
-             do_atest = 0;
-@@ -619,11 +561,6 @@ main(int argc, char **argv)
-         case 'C':
-             do_ctest = 1;
-             break;
--#if 0
--        case 'E':
--            do_etest = 1;
--            break;
--#endif
-         case 'K':
-             do_ktest = 1;
-             break;
-@@ -641,7 +578,7 @@ main(int argc, char **argv)
-             break;
-         default:
-             fprintf(stderr,
--                    "%s: usage is %s [-acekprsxvACEKPRSX]\n",
-+                    "%s: usage is %s [-acekprsxvACKPRSX]\n",
-                     argv[0], argv[0]);
-             exit(1);
-             break;
-@@ -682,14 +619,6 @@ main(int argc, char **argv)
-         if (kret)
-             goto fail;
-     }
--#if 0 /* code to be tested is currently disabled */
--    if (do_etest) {
--        ch_err = 'e';
--        kret = ser_eblock_test(kcontext, verbose);
--        if (kret)
--            goto fail;
--    }
--#endif
-     if (do_ptest) {
-         ch_err = 'p';
-         kret = ser_princ_test(kcontext, verbose);
-diff --git a/src/lib/krb5/krb/unparse.c b/src/lib/krb5/krb/unparse.c
-index 5bb64d00a..d94aa3cfa 100644
---- a/src/lib/krb5/krb/unparse.c
-+++ b/src/lib/krb5/krb/unparse.c
-@@ -122,13 +122,6 @@ copy_component_quoting(char *dest, const krb5_data *src, int flags)
-             *q++ = '\\';
-             *q++ = 'b';
-             break;
--#if 0
--            /* Heimdal escapes spaces in principal names upon unparsing */
--        case ' ':
--            *q++ = '\\';
--            *q++ = ' ';
--            break;
--#endif
-         case '\0':
-             *q++ = '\\';
-             *q++ = '0';
-diff --git a/src/lib/krb5/os/localaddr.c b/src/lib/krb5/os/localaddr.c
-index 58443f6e3..92d765f4b 100644
---- a/src/lib/krb5/os/localaddr.c
-+++ b/src/lib/krb5/os/localaddr.c
-@@ -392,20 +392,6 @@ get_linux_ipv6_addrs ()
-                 a6.s6_addr[i] = addrbyte[i];
-             if (scope != 0)
-                 continue;
--#if 0 /* These symbol names are as used by ifconfig, but none of the
--         system header files export them.  Dig up the kernel versions
--         someday and see if they're exported.  */
--            switch (scope) {
--            case 0:
--            default:
--                break;
--            case IPV6_ADDR_LINKLOCAL:
--            case IPV6_ADDR_SITELOCAL:
--            case IPV6_ADDR_COMPATv4:
--            case IPV6_ADDR_LOOPBACK:
--                continue;
--            }
--#endif
-             nw = calloc (1, sizeof (struct linux_ipv6_addr_list));
-             if (nw == 0)
-                 continue;
-@@ -1331,14 +1317,6 @@ krb5_os_localaddr(krb5_context context, krb5_address ***addr)
-     return get_localaddrs(context, addr, 1);
- }
- 
--#if 0 /* not actually used anywhere currently */
--krb5_error_code
--krb5int_local_addresses(krb5_context context, krb5_address ***addr)
--{
--    return get_localaddrs(context, addr, 0);
--}
--#endif
--
- static krb5_error_code
- get_localaddrs (krb5_context context, krb5_address ***addr, int use_profile)
- {
-diff --git a/src/lib/krb5/rcache/rc_io.c b/src/lib/krb5/rcache/rc_io.c
-index b9859fe9f..35fa14a1f 100644
---- a/src/lib/krb5/rcache/rc_io.c
-+++ b/src/lib/krb5/rcache/rc_io.c
-@@ -117,10 +117,6 @@ krb5_rc_io_mkstemp(krb5_context context, krb5_rc_iostuff *d, char *dir)
-     return 0;
- }
- 
--#if 0
--static krb5_error_code rc_map_errno (int) __attribute__((cold));
--#endif
--
- static krb5_error_code
- rc_map_errno (krb5_context context, int e, const char *fn,
-               const char *operation)
-diff --git a/src/lib/rpc/auth_gssapi.c b/src/lib/rpc/auth_gssapi.c
-index ace0be925..568ec6d87 100644
---- a/src/lib/rpc/auth_gssapi.c
-+++ b/src/lib/rpc/auth_gssapi.c
-@@ -744,14 +744,6 @@ skip_call:
-      }
- 
-      free(AUTH_PRIVATE(auth)->client_handle.value);
--
--#if 0
--     PRINTF(("gssapi_destroy: calling GSSAPI_EXIT\n"));
--     AUTH_PRIVATE(auth)->established = FALSE;
--     callstat = clnt_call(AUTH_PRIVATE(auth)->clnt, AUTH_GSSAPI_EXIT,
--			  xdr_void, NULL, xdr_void, NULL, timeout);
--#endif
--
-      free(auth->ah_private);
-      free(auth);
-      PRINTF(("gssapi_destroy: done\n"));
-diff --git a/src/lib/rpc/svc_auth.c b/src/lib/rpc/svc_auth.c
-index 5fedef7d7..e0f80af0b 100644
---- a/src/lib/rpc/svc_auth.c
-+++ b/src/lib/rpc/svc_auth.c
-@@ -59,9 +59,6 @@ static struct svcauthsw_type {
- } svcauthsw[] = {
-      {AUTH_GSSAPI, gssrpc__svcauth_gssapi},	/* AUTH_GSSAPI */
-      {AUTH_NONE, gssrpc__svcauth_none},		/* AUTH_NONE */
--#if 0
--     {AUTH_GSSAPI_COMPAT, gssrpc__svcauth_gssapi}, /* AUTH_GSSAPI_COMPAT */
--#endif
-      {AUTH_UNIX, gssrpc__svcauth_unix},		/* AUTH_UNIX */
-      {AUTH_SHORT, gssrpc__svcauth_short},	/* AUTH_SHORT */
-      {RPCSEC_GSS, gssrpc__svcauth_gss}		/* RPCSEC_GSS */
-diff --git a/src/lib/rpc/svc_auth_gssapi.c b/src/lib/rpc/svc_auth_gssapi.c
-index f3b3e35b8..384bdc336 100644
---- a/src/lib/rpc/svc_auth_gssapi.c
-+++ b/src/lib/rpc/svc_auth_gssapi.c
-@@ -869,10 +869,6 @@ done:
-      L_PRINTF(2, ("destroy_client: client %d destroyed\n", client_data->key));
- 
-      free(client_data);
--
--#if 0 /*ifdef PURIFY*/
--     purify_watch_n(client_data, sizeof(*client_data), "rw");
--#endif
- }
- 
- static void dump_db(char *msg)
-diff --git a/src/lib/win_glue.c b/src/lib/win_glue.c
-index 3d6dd7206..e149a1226 100644
---- a/src/lib/win_glue.c
-+++ b/src/lib/win_glue.c
-@@ -111,10 +111,6 @@ void GetCallingAppVerInfo( char *AppTitle, char *AppVer, char *AppIni,
- 		 * hey , I bet we don't have a version resource, let's
- 		 * punt
- 		 */
--#if 0
--		/* let's see what we have? (1813 means no resource) */
--		size = GetLastError(); 		/*  WIN32 only */
--#endif
- 		*VSflag = FALSE;
- 		return;
- 	}
-@@ -291,11 +287,6 @@ krb5_error_code krb5_vercheck()
- 		return retval;
- #endif
- #ifdef VERSERV
--#if 0
--	/* Check library ? */
--	if (CallVersionServer(APP_TITLE, APP_VER, APP_INI, NULL))
--		return KRB5_LIB_EXPIRED;
--#endif
- 	{
- #ifdef APP_TITLE
- 		if (CallVersionServer(APP_TITLE, APP_VER, APP_INI, NULL))
-diff --git a/src/plugins/kdb/db2/lockout.c b/src/plugins/kdb/db2/lockout.c
-index 3a4f41821..30fb554db 100644
---- a/src/plugins/kdb/db2/lockout.c
-+++ b/src/plugins/kdb/db2/lockout.c
-@@ -157,10 +157,6 @@ krb5_db2_lockout_audit(krb5_context context,
-     case KRB5KDC_ERR_PREAUTH_FAILED:
-     case KRB5KRB_AP_ERR_BAD_INTEGRITY:
-         break;
--#if 0
--    case KRB5KDC_ERR_CLIENT_REVOKED:
--        break;
--#endif
-     default:
-         return 0;
-     }
-diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c
-index 28dffe0c2..f6d00be9f 100644
---- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c
-+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c
-@@ -777,9 +777,6 @@ krb5_ldap_read_realm_params(krb5_context context, char *lrealm,
-     ent = ldap_first_entry (ld, result);
-     if (ent == NULL) {
-         ldap_get_option (ld, LDAP_OPT_ERROR_NUMBER, (void *) &st);
--#if 0
--        st = translate_ldap_error(st, OP_SEARCH);
--#endif
-         goto cleanup;
-     }
- 
-diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c
-index 77e9e5308..238101762 100644
---- a/src/plugins/preauth/pkinit/pkinit_clnt.c
-+++ b/src/plugins/preauth/pkinit/pkinit_clnt.c
-@@ -507,24 +507,6 @@ verify_kdc_san(krb5_context context,
-         for (hostptr = certhosts; *hostptr != NULL; hostptr++)
-             TRACE_PKINIT_CLIENT_SAN_KDCCERT_DNSNAME(context, *hostptr);
-     }
--#if 0
--    retval = call_san_checking_plugins(context, plgctx, reqctx, idctx,
--                                       princs, hosts, &plugin_decision,
--                                       need_eku_checking);
--    pkiDebug("%s: call_san_checking_plugins() returned retval %d\n",
--             __FUNCTION__);
--    if (retval) {
--        retval = KRB5KDC_ERR_KDC_NAME_MISMATCH;
--        goto out;
--    }
--    pkiDebug("%s: call_san_checking_plugins() returned decision %d and "
--             "need_eku_checking %d\n",
--             __FUNCTION__, plugin_decision, *need_eku_checking);
--    if (plugin_decision != NO_DECISION) {
--        retval = plugin_decision;
--        goto out;
--    }
--#endif
- 
-     pkiDebug("%s: Checking pkinit sans\n", __FUNCTION__);
-     for (i = 0; princs != NULL && princs[i] != NULL; i++) {
-diff --git a/src/plugins/preauth/pkinit/pkinit_matching.c b/src/plugins/preauth/pkinit/pkinit_matching.c
-index c2a4c084d..afcce3f8b 100644
---- a/src/plugins/preauth/pkinit/pkinit_matching.c
-+++ b/src/plugins/preauth/pkinit/pkinit_matching.c
-@@ -572,17 +572,6 @@ check_all_certs(krb5_context context,
-      */
-     for (i = 0, md = matchdata[i]; md != NULL; md = matchdata[++i]) {
-         pkiDebug("%s: subject: '%s'\n", __FUNCTION__, md->subject_dn);
--#if 0
--        pkiDebug("%s: issuer:  '%s'\n", __FUNCTION__, md->subject_dn);
--        for (j = 0; md->sans != NULL && md->sans[j] != NULL; j++) {
--            char *san_string;
--            krb5_unparse_name(context, md->sans[j], &san_string);
--            pkiDebug("%s: PKINIT san: '%s'\n", __FUNCTION__, san_string);
--            krb5_free_unparsed_name(context, san_string);
--        }
--        for (j = 0; md->upns != NULL && md->upns[j] != NULL; j++)
--            pkiDebug("%s: UPN san: '%s'\n", __FUNCTION__, md->upns[j]);
--#endif
-         certs_checked++;
-         for (rc = rs->crs; rc != NULL; rc = rc->next) {
-             comp_match = component_match(context, rc, md);
-diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
-index 76ad5bf19..27e6ef4d2 100644
---- a/src/plugins/preauth/pkinit/pkinit_srv.c
-+++ b/src/plugins/preauth/pkinit/pkinit_srv.c
-@@ -204,24 +204,6 @@ verify_client_san(krb5_context context,
-         goto out;
-     }
- 
--    /* XXX Verify this is consistent with client side XXX */
--#if 0
--    retval = call_san_checking_plugins(context, plgctx, reqctx, princs,
--                                       upns, NULL, &plugin_decision, &ignore);
--    pkiDebug("%s: call_san_checking_plugins() returned retval %d\n",
--             __FUNCTION__);
--    if (retval) {
--        retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
--        goto cleanup;
--    }
--    pkiDebug("%s: call_san_checking_plugins() returned decision %d\n",
--             __FUNCTION__, plugin_decision);
--    if (plugin_decision != NO_DECISION) {
--        retval = plugin_decision;
--        goto out;
--    }
--#endif
--
- #ifdef DEBUG_SAN_INFO
-     krb5_unparse_name(context, client, &client_string);
- #endif
-diff --git a/src/tests/asn.1/krb5_decode_leak.c b/src/tests/asn.1/krb5_decode_leak.c
-index 22601c7bf..77fd3ee40 100644
---- a/src/tests/asn.1/krb5_decode_leak.c
-+++ b/src/tests/asn.1/krb5_decode_leak.c
-@@ -633,18 +633,6 @@ main(int argc, char **argv)
-                   krb5_free_ad_kdcissued);
-         ktest_empty_ad_kdcissued(&kdci);
-     }
--#if 0
--    /****************************************************************/
--    /* encode_krb5_ad_signedpath_data */
--    {
--        krb5_ad_signedpath_data spd, *tmp;
--        ktest_make_sample_ad_signedpath_data(&spd);
--        leak_test(spd, encode_krb5_ad_signedpath_data,
--                  decode_krb5_ad_signedpath_data,
--                  NULL);
--        ktest_empty_ad_signedpath_data(&spd);
--    }
--#endif
-     /****************************************************************/
-     /* encode_krb5_ad_signedpath */
-     {
-diff --git a/src/tests/dejagnu/config/default.exp b/src/tests/dejagnu/config/default.exp
-index 2d1686c56..daf3c7d3b 100644
---- a/src/tests/dejagnu/config/default.exp
-+++ b/src/tests/dejagnu/config/default.exp
-@@ -32,26 +32,6 @@ set tgt_support_desmd5 0
- # request a des-cbc-md4 session key.  Since only des-cbc-crc is in the
- # KDC's permitted_enctypes list, the TGT will be unusable.
- 
--# KLUDGE for tracking down leaking ptys
--if 0 {
--    rename spawn oldspawn
--    rename wait oldwait
--    proc spawn { args } {
--	upvar 1 spawn_id spawn_id
--	verbose "spawn: args=$args"
--	set pid [eval oldspawn $args]
--	verbose "spawn: pid=$pid spawn_id=$spawn_id"
--	return $pid
--    }
--    proc wait { args } {
--	upvar 1 spawn_id spawn_id
--	verbose "wait: args=$args"
--	set ret [eval oldwait $args]
--	verbose "wait: $ret"
--	return $ret
--    }
--}
--
- if { [string length $VALGRIND] } {
-     rename spawn valgrind_aux_spawn
-     proc spawn { args } {
-diff --git a/src/tests/shlib/t_loader.c b/src/tests/shlib/t_loader.c
-index 869be800a..29481a7be 100644
---- a/src/tests/shlib/t_loader.c
-+++ b/src/tests/shlib/t_loader.c
-@@ -186,18 +186,6 @@ int main()
- 
-     (void) setvbuf(stdout, 0, _IONBF, 0);
- 
--#if 0
--    /* Simplest test: Load, then unload out of order.  */
--    celib = do_open("com_err", "3.0", 0);
--    k5lib = do_open("krb5", "3.2", 0);
--    gsslib = do_open("gssapi_krb5", "2.2", 0);
--    celib2 = do_open("com_err", "3.0", 0);
--    do_close(celib);
--    do_close(k5lib);
--    do_close(celib2);
--    do_close(gsslib);
--#endif
--
-     celib = do_open("com_err", "3.0", 0);
-     k5lib = do_open("krb5", "3.2", 0);
-     gsslib = do_open("gssapi_krb5", "2.2", 0);
-diff --git a/src/tests/threads/t_rcache.c b/src/tests/threads/t_rcache.c
-index d6187f061..9d9b1acd3 100644
---- a/src/tests/threads/t_rcache.c
-+++ b/src/tests/threads/t_rcache.c
-@@ -106,7 +106,6 @@ static void try_one (struct tinfo *t)
- static void *run_a_loop (void *x)
- {
-     struct tinfo t = { 0 };
--/*    int chr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"[(*(int*)x) % 27]; */
- 
-     t.now = time(0);
-     t.idx = *(int *)x;
-@@ -117,12 +116,7 @@ static void *run_a_loop (void *x)
-         t.now = time(0);
-         try_one(&t);
-         t.total++;
--#if 0
--        printf("%c", chr);
--        fflush(stdout);
--#endif
-     }
--/*    printf("thread %u total %u\n", (unsigned) ((int *)x-ip), t.total);*/
-     *(int*)x = t.total;
-     return 0;
- }
-diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c
-index 0f5462aea..64b32dbf1 100644
---- a/src/util/profile/prof_file.c
-+++ b/src/util/profile/prof_file.c
-@@ -79,39 +79,6 @@ void profile_library_finalizer(void)
- 
- static void profile_free_file_data(prf_data_t);
- 
--#if 0
--
--#define scan_shared_trees_locked()                              \
--    {                                                           \
--        prf_data_t d;                                           \
--        k5_mutex_assert_locked(&g_shared_trees_mutex);          \
--        for (d = g_shared_trees; d; d = d->next) {              \
--            assert(d->magic == PROF_MAGIC_FILE_DATA);           \
--            assert((d->flags & PROFILE_FILE_SHARED) != 0);      \
--            assert(d->filespec[0] != 0);                        \
--            assert(d->fslen <= 1000); /* XXX */                 \
--            assert(d->filespec[d->fslen] == 0);                 \
--            assert(d->fslen = strlen(d->filespec));             \
--            assert(d->root != NULL);                            \
--        }                                                       \
--    }
--
--#define scan_shared_trees_unlocked()                    \
--    {                                                   \
--        int r;                                          \
--        r = k5_mutex_lock(&g_shared_trees_mutex);       \
--        assert (r == 0);                                \
--        scan_shared_trees_locked();                     \
--        k5_mutex_unlock(&g_shared_trees_mutex);         \
--    }
--
--#else
--
--#define scan_shared_trees_locked()      { ; }
--#define scan_shared_trees_unlocked()    { ; }
--
--#endif
--
- static int rw_access(const_profile_filespec_t filespec)
- {
- #ifdef HAVE_ACCESS
-@@ -209,8 +176,6 @@ errcode_t profile_open_file(const_profile_filespec_t filespec,
-     if (retval)
-         return retval;
- 
--    scan_shared_trees_unlocked();
--
-     prf = malloc(sizeof(struct _prf_file_t));
-     if (!prf)
-         return ENOMEM;
-@@ -244,7 +209,6 @@ errcode_t profile_open_file(const_profile_filespec_t filespec,
-     }
- 
-     k5_mutex_lock(&g_shared_trees_mutex);
--    scan_shared_trees_locked();
-     for (data = g_shared_trees; data; data = data->next) {
-         if (!strcmp(data->filespec, expanded_filename)
-             /* Check that current uid has read access.  */
-@@ -264,7 +228,6 @@ errcode_t profile_open_file(const_profile_filespec_t filespec,
-         }
-         prf->data = data;
-         *ret_prof = prf;
--        scan_shared_trees_unlocked();
-         return 0;
-     }
-     k5_mutex_unlock(&g_shared_trees_mutex);
-@@ -291,11 +254,9 @@ errcode_t profile_open_file(const_profile_filespec_t filespec,
-     }
- 
-     k5_mutex_lock(&g_shared_trees_mutex);
--    scan_shared_trees_locked();
-     data->flags |= PROFILE_FILE_SHARED;
-     data->next = g_shared_trees;
-     g_shared_trees = data;
--    scan_shared_trees_locked();
-     k5_mutex_unlock(&g_shared_trees_mutex);
- 
-     *ret_prof = prf;
-@@ -537,11 +498,9 @@ void profile_dereference_data(prf_data_t data)
- }
- void profile_dereference_data_locked(prf_data_t data)
- {
--    scan_shared_trees_locked();
-     data->refcount--;
-     if (data->refcount == 0)
-         profile_free_file_data(data);
--    scan_shared_trees_locked();
- }
- 
- void profile_lock_global()
-@@ -562,7 +521,6 @@ void profile_free_file(prf_file_t prf)
- /* Call with mutex locked!  */
- static void profile_free_file_data(prf_data_t data)
- {
--    scan_shared_trees_locked();
-     if (data->flags & PROFILE_FILE_SHARED) {
-         /* Remove from linked list.  */
-         if (g_shared_trees == data)
-@@ -586,7 +544,6 @@ static void profile_free_file_data(prf_data_t data)
-     data->magic = 0;
-     k5_mutex_destroy(&data->lock);
-     free(data);
--    scan_shared_trees_locked();
- }
- 
- errcode_t profile_close_file(prf_file_t prf)
-diff --git a/src/util/support/fake-addrinfo.c b/src/util/support/fake-addrinfo.c
-index 3ee162e0d..0fb35cf15 100644
---- a/src/util/support/fake-addrinfo.c
-+++ b/src/util/support/fake-addrinfo.c
-@@ -888,16 +888,10 @@ fake_getaddrinfo (const char *name, const char *serv,
-        If it's not set, don't accept such names.  */
-     if (flags & AI_NUMERICHOST) {
-         struct in_addr addr4;
--#if 0
--        ret = inet_aton (name, &addr4);
--        if (ret)
--            return EAI_NONAME;
--#else
-         addr4.s_addr = inet_addr (name);
-         if (addr4.s_addr == 0xffffffff || addr4.s_addr == -1)
-             /* 255.255.255.255 or parse error, both bad */
-             return EAI_NONAME;
--#endif
-         ret = fai_add_entry (&res, &addr4, port, &template);
-     } else {
-         ret = fai_add_hosts_by_name (name, &template, port, flags,
-diff --git a/src/util/support/utf8.c b/src/util/support/utf8.c
-index 34e2b6adb..ea8818116 100644
---- a/src/util/support/utf8.c
-+++ b/src/util/support/utf8.c
-@@ -404,28 +404,6 @@ int krb5int_utf8_isalnum(const char * p)
- 
-     return KRB5_ALNUM(c);
- }
--
--#if 0
--int krb5int_utf8_islower(const char * p)
--{
--    unsigned c = * (const unsigned char *) p;
--
--    if (!KRB5_ASCII(c))
--        return 0;
--
--    return KRB5_LOWER(c);
--}
--
--int krb5int_utf8_isupper(const char * p)
--{
--    unsigned c = * (const unsigned char *) p;
--
--    if (!KRB5_ASCII(c))
--        return 0;
--
--    return KRB5_UPPER(c);
--}
--#endif
- #endif
- 
- 
-diff --git a/src/windows/include/loadfuncs-krb5.h b/src/windows/include/loadfuncs-krb5.h
-index a90678878..39a3504f6 100644
---- a/src/windows/include/loadfuncs-krb5.h
-+++ b/src/windows/include/loadfuncs-krb5.h
-@@ -106,29 +106,6 @@ TYPEDEF_FUNC(
-     krb5_free_ap_rep,
-     (krb5_context, krb5_ap_rep * )
-     );
--
--/* Removed around the time of krb5_rc_* change... */
--#if 0
--TYPEDEF_FUNC(
--    void,
--    KRB5_CALLCONV,
--    krb5_free_safe,
--    (krb5_context, krb5_safe * )
--    );
--TYPEDEF_FUNC(
--    void,
--    KRB5_CALLCONV,
--    krb5_free_priv,
--    (krb5_context, krb5_priv * )
--    );
--TYPEDEF_FUNC(
--    void,
--    KRB5_CALLCONV,
--    krb5_free_priv_enc_part,
--    (krb5_context, krb5_priv_enc_part * )
--    );
--#endif
--
- TYPEDEF_FUNC(
-     void,
-     KRB5_CALLCONV,
-diff --git a/src/windows/kfwlogon/kfwlogon.c b/src/windows/kfwlogon/kfwlogon.c
-index d851c4685..c388fffcd 100644
---- a/src/windows/kfwlogon/kfwlogon.c
-+++ b/src/windows/kfwlogon/kfwlogon.c
-@@ -434,9 +434,6 @@ static BOOL
- GetSecurityLogonSessionData(HANDLE hToken, PSECURITY_LOGON_SESSION_DATA * ppSessionData)
- {
-     NTSTATUS Status = 0;
--#if 0
--    HANDLE  TokenHandle;
--#endif
-     TOKEN_STATISTICS Stats;
-     DWORD   ReqLen;
-     BOOL    Success;
-@@ -445,16 +442,8 @@ GetSecurityLogonSessionData(HANDLE hToken, PSECURITY_LOGON_SESSION_DATA * ppSess
-         return FALSE;
-     *ppSessionData = NULL;
- 
--#if 0
--    Success = OpenProcessToken( HANDLE GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
--    if ( !Success )
--        return FALSE;
--#endif
- 
-     Success = GetTokenInformation( hToken, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
--#if 0
--    CloseHandle( TokenHandle );
--#endif
-     if ( !Success )
-         return FALSE;
- 
-diff --git a/src/windows/leash/Leash.cpp b/src/windows/leash/Leash.cpp
-index f4e749350..cafcda7ce 100644
---- a/src/windows/leash/Leash.cpp
-+++ b/src/windows/leash/Leash.cpp
-@@ -46,8 +46,6 @@
- static char THIS_FILE[] = __FILE__;
- #endif
- 
--extern "C" int VScheckVersion(HWND hWnd, HANDLE hThisInstance);
--
- TicketInfoWrapper ticketinfo;
- 
- HWND CLeashApp::m_hProgram = 0;
-@@ -479,8 +477,6 @@ BOOL CLeashApp::InitInstance()
-         }
-     }
- 
--    VScheckVersion(m_pMainWnd->m_hWnd, AfxGetInstanceHandle());
--
-     // The one and only window has been initialized, so show and update it.
-     m_pMainWnd->SetWindowText("MIT Kerberos");
-     m_pMainWnd->UpdateWindow();
-diff --git a/src/windows/leash/Makefile.in b/src/windows/leash/Makefile.in
-index 1b124e90f..57f93a418 100644
---- a/src/windows/leash/Makefile.in
-+++ b/src/windows/leash/Makefile.in
-@@ -61,9 +61,6 @@ OBJS=   \
- 	$(OUTPRE)MainFrm.obj \
- 	$(OUTPRE)out2con.obj \
- 	$(OUTPRE)StdAfx.obj \
--	$(OUTPRE)AfsProperties.obj \
--	$(OUTPRE)VSroutines.obj \
--	$(OUTPRE)KrbMiscConfigOpt.obj \
- 	$(OUTPRE)KrbListTickets.obj
- 
- RESFILE = $(OUTPRE)Leash.res
-diff --git a/src/windows/leash/VSroutines.c b/src/windows/leash/VSroutines.c
-deleted file mode 100644
-index 63f0b4ae1..000000000
---- a/src/windows/leash/VSroutines.c
-+++ /dev/null
-@@ -1,64 +0,0 @@
--#include <windows.h>
--#include <winver.h>
--
--#if 0
--//#ifdef USE_VS
--#include <vs.h>
--
--#define ININAME	"leash.ini"
--
--int VScheckVersion(HWND hWnd, HANDLE hThisInstance)
--{
--    VS_Request		vrequest;
--    VS_Status		status;
--    BOOL		ok_to_continue;
--    HCURSOR		hcursor;
--    char		szFilename[255];
--    char		szVerQ[90];
--    char		*cp;
--    LPSTR		lpAppVersion;
--    LPSTR		lpAppName;
--    LONG FAR		*lpLangInfo;
--    DWORD		hVersionInfoID;
--    DWORD		size;
--    GLOBALHANDLE	hVersionInfo;
--    LPSTR		lpVersionInfo;
--    int			dumint;
--    int			retval;
--
--    GetModuleFileName(hThisInstance, (LPSTR)szFilename, 255);
--    size = GetFileVersionInfoSize((LPSTR) szFilename, &hVersionInfoID);
--    hVersionInfo = GlobalAlloc(GHND, size);
--    lpVersionInfo = GlobalLock(hVersionInfo);
--    retval = GetFileVersionInfo(szFilename, hVersionInfoID, size,
--                                lpVersionInfo);
--    retval = VerQueryValue(lpVersionInfo, "\\VarFileInfo\\Translation",
--                           (LPSTR FAR *)&lpLangInfo, &dumint);
--    wsprintf(szVerQ, "\\StringFileInfo\\%04x%04x\\",
--             LOWORD(*lpLangInfo), HIWORD(*lpLangInfo));
--    cp = szVerQ + lstrlen(szVerQ);
--    lstrcpy(cp, "ProductName");
--    retval = VerQueryValue(lpVersionInfo, szVerQ, &lpAppName, &dumint);
--    lstrcpy(cp, "ProductVersion");
--
--    retval = VerQueryValue(lpVersionInfo, szVerQ, &lpAppVersion, &dumint);
--    hcursor = SetCursor(LoadCursor((HINSTANCE)NULL, IDC_WAIT));
--    vrequest = VSFormRequest(lpAppName, lpAppVersion, ININAME, NULL, hWnd,
--                             V_CHECK_AND_LOG);
--    if ((ok_to_continue = (ReqStatus(vrequest) != V_E_CANCEL))
--        && v_complain((status = VSProcessRequest(vrequest)), ININAME))
--        WinVSReportRequest(vrequest, hWnd, "Version Server Status Report");
--    if (ok_to_continue && status == V_REQUIRED)
--        ok_to_continue = FALSE;
--    VSDestroyRequest(vrequest);
--    SetCursor(hcursor);
--    GlobalUnlock(hVersionInfo);
--    GlobalFree(hVersionInfo);
--    return(ok_to_continue);
--}
--#else
--int VScheckVersion(HWND hWnd, HANDLE hThisInstance)
--{
--    return(1);
--}
--#endif
-diff --git a/src/windows/leashdll/lsh_pwd.c b/src/windows/leashdll/lsh_pwd.c
-index ac85625a0..7cbe3d7e4 100644
---- a/src/windows/leashdll/lsh_pwd.c
-+++ b/src/windows/leashdll/lsh_pwd.c
-@@ -1426,11 +1426,6 @@ AuthenticateProc(
-         CSetDlgItemText(hDialog, IDC_EDIT_PRINCIPAL, principal);
-         CSetDlgItemText(hDialog, IDC_EDIT_PASSWORD, "");
- 
--#if 0  /* 20030619 - mjv wishes to return to the default character */
--        /* echo spaces */
--	CSendDlgItemMessage(hDialog, IDC_EDIT_PASSWORD, EM_SETPASSWORDCHAR, 32, 0);
--#endif
--
- 	/* Set Lifetime Slider
- 	*   min value = 5
- 	*   max value = 1440
-@@ -1817,12 +1812,6 @@ NewPasswordProc(
-         if (hEditCtrl)
-             pAutoComplete = Leash_pec_create(hEditCtrl);
- 
--#if 0  /* 20030619 - mjv wishes to return to the default character */
--	/* echo spaces */
--	CSendDlgItemMessage(hDialog, IDC_EDIT_PASSWORD, EM_SETPASSWORDCHAR, 32, 0);
--	CSendDlgItemMessage(hDialog, IDC_EDIT_PASSWORD2, EM_SETPASSWORDCHAR, 32, 0);
--	CSendDlgItemMessage(hDialog, IDC_EDIT_PASSWORD3, EM_SETPASSWORDCHAR, 32, 0);
--#endif
-         /* setup text of stuff. */
- 
-         if (Position.x > 0 && Position.y > 0 &&
-diff --git a/src/windows/leashdll/lshfunc.c b/src/windows/leashdll/lshfunc.c
-index 8dafb7bed..47337de5d 100644
---- a/src/windows/leashdll/lshfunc.c
-+++ b/src/windows/leashdll/lshfunc.c
-@@ -279,19 +279,11 @@ Leash_changepwd_v5(
-     if ( !pkrb5_init_context )
-         goto cleanup;
- 
--   if (rc = pkrb5_init_context(&context)) {
--#if 0
--       com_err(argv[0], ret, "initializing kerberos library");
--#endif
-+   if (rc = pkrb5_init_context(&context))
-        goto cleanup;
--   }
- 
--   if (rc = pkrb5_parse_name(context, principal, &princ)) {
--#if 0
--       com_err(argv[0], ret, "parsing client name");
--#endif
-+   if (rc = pkrb5_parse_name(context, principal, &princ))
-        goto cleanup;
--   }
- 
-    pkrb5_get_init_creds_opt_init(&opts);
-    pkrb5_get_init_creds_opt_set_tkt_life(&opts, 5*60);
-@@ -305,29 +297,13 @@ Leash_changepwd_v5(
- 
- 
-    if (rc = pkrb5_get_init_creds_password(context, &creds, princ, password,
--                                          0, 0, 0, "kadmin/changepw", &opts)) {
--       if (rc == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
--#if 0
--           com_err(argv[0], 0,
--                   "Password incorrect while getting initial ticket");
--#endif
--       }
--       else {
--#if 0
--           com_err(argv[0], ret, "getting initial ticket");
--#endif
--       }
-+                                          0, 0, 0, "kadmin/changepw", &opts))
-        goto cleanup;
--   }
- 
-    if (rc = pkrb5_change_password(context, &creds, newpassword,
-                                   &result_code, &result_code_string,
--                                  &result_string)) {
--#if 0
--       com_err(argv[0], ret, "changing password");
--#endif
-+                                  &result_string))
-        goto cleanup;
--   }
- 
-    if (result_code) {
-        int len = result_code_string.length +
-diff --git a/src/windows/leashdll/lshutil.cpp b/src/windows/leashdll/lshutil.cpp
-index 37c0723f3..a90e7e92e 100644
---- a/src/windows/leashdll/lshutil.cpp
-+++ b/src/windows/leashdll/lshutil.cpp
-@@ -531,17 +531,6 @@ protected:
-             IAutoCompleteDropDown* pacdd = NULL;
-             hRes = pac->QueryInterface(IID_IAutoCompleteDropDown, (LPVOID*)&pacdd);
-             pac->Release();
--
--        // @TODO: auto-suggest; other advanced options?
--#if 0
--            IAutoComplete2 *pac2;
--
--            if (SUCCEEDED(pac->QueryInterface(IID_IAutoComplete2,
--                                              (LPVOID*)&pac2))) {
--                pac2->SetOptions(ACO_AUTOSUGGEST);
--                pac2->Release();
--            }
--#endif
-             m_acdd = pacdd;
-         }
-     }
-diff --git a/src/windows/lib/cacheapi.h b/src/windows/lib/cacheapi.h
-index c485080c1..b30857810 100644
---- a/src/windows/lib/cacheapi.h
-+++ b/src/windows/lib/cacheapi.h
-@@ -102,21 +102,6 @@ typedef struct opaque_dll_control_block_type* apiCB;
- typedef struct opaque_ccache_pointer_type* ccache_p;
- typedef struct opaque_credential_iterator_type* ccache_cit;
- 
--#if 0
--enum _cc_data_type {
--    type_ticket = 0,                /* 0 for ticket, second_ticket */
--    /* Ted's draft spec says these are to be
--       "as defined in the Kerberos V5 protocol"
--       all I can find are typdefs,
--       can't find an enumerated type or #define
--    */
--    type_address,           /* =  <"as defined in the Kerberos V5 protocol"> */
--    type_authdata,          /* = <"as defined in the Kerberos V5 protocol"> */
--    type_encryption,        /* = <"as defined in the Kerberos V5 protocol"> */
--    cc_data_type_max        /* for validation */
--};
--#endif
--
- typedef struct _cc_data
- {
-     cc_uint32       type;		// should be one of _cc_data_type
diff --git a/SOURCES/Exit-with-status-0-from-kadmind.patch b/SOURCES/Exit-with-status-0-from-kadmind.patch
deleted file mode 100644
index 5fbdff8..0000000
--- a/SOURCES/Exit-with-status-0-from-kadmind.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 3bfe632c7011c335362d78356232507d9ee26f73 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Wed, 14 Mar 2018 14:31:22 -0400
-Subject: [PATCH] Exit with status 0 from kadmind
-
-Typically, 0 denotes successful exit.  In particular, init systems
-will complain if another different value is returned.  This presents a
-problem for automated installation jobs which want to restart kadmind.
-
-`service kadmin stop` typically sends SIGTERM, which is caught by
-verto and passed to our handler.  Besides cleanup, we then call
-verto_break(), which causes the verto_run() event loop to return.  The
-weird return code has been present since the addition of the kadmin
-code, which used a similar event model for signals.
-
-(cherry picked from commit f970ad412aca36f8a7d3addb1cd4026ed22e5592)
----
- src/kadmin/server/ovsec_kadmd.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/kadmin/server/ovsec_kadmd.c b/src/kadmin/server/ovsec_kadmd.c
-index aac4d4ffd..0a28b2384 100644
---- a/src/kadmin/server/ovsec_kadmd.c
-+++ b/src/kadmin/server/ovsec_kadmd.c
-@@ -559,5 +559,5 @@ main(int argc, char *argv[])
- 
-     krb5_klog_close(context);
-     krb5_free_context(context);
--    exit(2);
-+    exit(0);
- }
diff --git a/SOURCES/Explicitly-look-for-python2-in-configure.in.patch b/SOURCES/Explicitly-look-for-python2-in-configure.in.patch
deleted file mode 100644
index cb6620f..0000000
--- a/SOURCES/Explicitly-look-for-python2-in-configure.in.patch
+++ /dev/null
@@ -1,816 +0,0 @@
-From 1d0c0db7755076834519fd02c271a78bbf26bb19 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Tue, 3 Jul 2018 01:20:50 -0400
-Subject: [PATCH] Explicitly look for python2 in configure.in
-
-The executable "python" has traditionally been Python 2, but is
-becoming more ambiguous as operating systems transition towards Python
-3.  Look for "python2" in the path in preference to "python", and
-check that what we found isn't Python 3.
-
-Remove the "#!/usr/bin/python" headers at the start of Python test
-scripts since we run them explicitly under python, not as executables.
-Execute paste-kdcproxy.py via sys.executable in t_proxy.py so that it
-doesn't need a #!/usr/bin/python header.
-
-ticket: 8709 (new)
-(cherry picked from commit 2bd410ecdb366083fe9b4e5f6ac4b741b624230b)
----
- src/appl/gss-sample/t_gss_sample.py     | 2 --
- src/appl/user_user/t_user2user.py       | 1 -
- src/configure.in                        | 9 ++++++---
- src/kadmin/dbutil/t_tdumputil.py        | 2 --
- src/kdc/t_bigreply.py                   | 1 -
- src/kdc/t_emptytgt.py                   | 1 -
- src/kdc/t_workers.py                    | 1 -
- src/lib/kdb/t_stringattr.py             | 1 -
- src/lib/krad/t_daemon.py                | 2 --
- src/lib/krb5/ccache/t_cccol.py          | 1 -
- src/lib/krb5/krb/t_expire_warn.py       | 2 --
- src/lib/krb5/krb/t_in_ccache_patypes.py | 2 --
- src/lib/krb5/krb/t_vfy_increds.py       | 2 --
- src/lib/krb5/os/t_discover_uri.py       | 1 -
- src/tests/gssapi/t_authind.py           | 1 -
- src/tests/gssapi/t_ccselect.py          | 2 --
- src/tests/gssapi/t_client_keytab.py     | 1 -
- src/tests/gssapi/t_enctypes.py          | 1 -
- src/tests/gssapi/t_export_cred.py       | 1 -
- src/tests/gssapi/t_gssapi.py            | 1 -
- src/tests/gssapi/t_s4u.py               | 1 -
- src/tests/jsonwalker.py                 | 2 --
- src/tests/t_audit.py                    | 1 -
- src/tests/t_authdata.py                 | 1 -
- src/tests/t_bogus_kdc_req.py            | 2 --
- src/tests/t_ccache.py                   | 2 --
- src/tests/t_certauth.py                 | 1 -
- src/tests/t_changepw.py                 | 1 -
- src/tests/t_crossrealm.py               | 2 --
- src/tests/t_cve-2012-1014.py            | 2 --
- src/tests/t_cve-2012-1015.py            | 2 --
- src/tests/t_cve-2013-1416.py            | 2 --
- src/tests/t_cve-2013-1417.py            | 2 --
- src/tests/t_dump.py                     | 1 -
- src/tests/t_errmsg.py                   | 1 -
- src/tests/t_etype_info.py               | 1 -
- src/tests/t_general.py                  | 1 -
- src/tests/t_hooks.py                    | 1 -
- src/tests/t_hostrealm.py                | 1 -
- src/tests/t_iprop.py                    | 2 --
- src/tests/t_kadm5_auth.py               | 1 -
- src/tests/t_kadm5_hook.py               | 1 -
- src/tests/t_kadmin_acl.py               | 1 -
- src/tests/t_kadmin_parsing.py           | 1 -
- src/tests/t_kdb.py                      | 1 -
- src/tests/t_kdb_locking.py              | 2 --
- src/tests/t_kdc_log.py                  | 2 --
- src/tests/t_kdcpolicy.py                | 1 -
- src/tests/t_keydata.py                  | 1 -
- src/tests/t_keyrollover.py              | 1 -
- src/tests/t_keytab.py                   | 1 -
- src/tests/t_kprop.py                    | 1 -
- src/tests/t_localauth.py                | 1 -
- src/tests/t_mkey.py                     | 1 -
- src/tests/t_otp.py                      | 2 --
- src/tests/t_pkinit.py                   | 1 -
- src/tests/t_policy.py                   | 1 -
- src/tests/t_preauth.py                  | 1 -
- src/tests/t_princflags.py               | 1 -
- src/tests/t_proxy.py                    | 4 ++--
- src/tests/t_pwqual.py                   | 1 -
- src/tests/t_rdreq.py                    | 1 -
- src/tests/t_referral.py                 | 1 -
- src/tests/t_renew.py                    | 1 -
- src/tests/t_renprinc.py                 | 2 --
- src/tests/t_salt.py                     | 1 -
- src/tests/t_sesskeynego.py              | 1 -
- src/tests/t_skew.py                     | 1 -
- src/tests/t_sn2princ.py                 | 1 -
- src/tests/t_spake.py                    | 1 -
- src/tests/t_stringattr.py               | 2 --
- src/tests/t_tabdump.py                  | 1 -
- src/tests/t_unlockiter.py               | 1 -
- src/tests/t_y2038.py                    | 1 -
- src/util/paste-kdcproxy.py              | 1 -
- 75 files changed, 8 insertions(+), 99 deletions(-)
-
-diff --git a/src/appl/gss-sample/t_gss_sample.py b/src/appl/gss-sample/t_gss_sample.py
-index 0299e4590..2f537823a 100755
---- a/src/appl/gss-sample/t_gss_sample.py
-+++ b/src/appl/gss-sample/t_gss_sample.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- # Copyright (C) 2010 by the Massachusetts Institute of Technology.
- # All rights reserved.
- #
-diff --git a/src/appl/user_user/t_user2user.py b/src/appl/user_user/t_user2user.py
-index 2a7d03f8d..2c054f181 100755
---- a/src/appl/user_user/t_user2user.py
-+++ b/src/appl/user_user/t_user2user.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # If uuserver is not compiled under -DDEBUG, then set to 0
-diff --git a/src/configure.in b/src/configure.in
-index 08c63beca..3f45784b5 100644
---- a/src/configure.in
-+++ b/src/configure.in
-@@ -1098,13 +1098,16 @@ fi
- AC_SUBST(HAVE_RUNTEST)
- 
- # For Python tests.
--AC_CHECK_PROG(PYTHON,python,python)
-+AC_CHECK_PROG(PYTHON,python2,python2)
-+if text x"$PYTHON" = x; then
-+	AC_CHECK_PROG(PYTHON,python,python)
-+fi
- HAVE_PYTHON=no
- if test x"$PYTHON" != x; then
- 	# k5test.py requires python 2.4 (for the subprocess module).
- 	# Some code needs python 2.5 (for syntax like conditional expressions).
--	vercheck="import sys;sys.exit((sys.hexversion < 0x2050000) and 1 or 0)"
--	if python -c "$vercheck"; then
-+	wantver="(sys.hexversion >= 0x2050000 and sys.hexversion < 0x3000000)"
-+	if "$PYTHON" -c "import sys; sys.exit(not $wantver and 1 or 0)"; then
- 		HAVE_PYTHON=yes
- 	fi
- fi
-diff --git a/src/kadmin/dbutil/t_tdumputil.py b/src/kadmin/dbutil/t_tdumputil.py
-index 5d7ac38d2..52e356533 100755
---- a/src/kadmin/dbutil/t_tdumputil.py
-+++ b/src/kadmin/dbutil/t_tdumputil.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- from k5test import *
- from subprocess import *
- 
-diff --git a/src/kdc/t_bigreply.py b/src/kdc/t_bigreply.py
-index 6bc9a8fe0..b6300154f 100644
---- a/src/kdc/t_bigreply.py
-+++ b/src/kdc/t_bigreply.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # Set the maximum UDP reply size very low, so that all replies go
-diff --git a/src/kdc/t_emptytgt.py b/src/kdc/t_emptytgt.py
-index 2d0432e33..c601c010c 100755
---- a/src/kdc/t_emptytgt.py
-+++ b/src/kdc/t_emptytgt.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- realm = K5Realm(create_host=False)
-diff --git a/src/kdc/t_workers.py b/src/kdc/t_workers.py
-index 6dd4f6805..8de3f34d9 100755
---- a/src/kdc/t_workers.py
-+++ b/src/kdc/t_workers.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- realm = K5Realm(start_kdc=False, create_host=False)
-diff --git a/src/lib/kdb/t_stringattr.py b/src/lib/kdb/t_stringattr.py
-index 085e179e4..93e2b0c01 100755
---- a/src/lib/kdb/t_stringattr.py
-+++ b/src/lib/kdb/t_stringattr.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- realm = K5Realm(create_kdb=False)
-diff --git a/src/lib/krad/t_daemon.py b/src/lib/krad/t_daemon.py
-index dcda0050b..7d7a5d0c8 100755
---- a/src/lib/krad/t_daemon.py
-+++ b/src/lib/krad/t_daemon.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--#
- # Copyright 2013 Red Hat, Inc.  All rights reserved.
- #
- # Redistribution and use in source and binary forms, with or without
-diff --git a/src/lib/krb5/ccache/t_cccol.py b/src/lib/krb5/ccache/t_cccol.py
-index f7f178564..1467512e2 100755
---- a/src/lib/krb5/ccache/t_cccol.py
-+++ b/src/lib/krb5/ccache/t_cccol.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- realm = K5Realm(create_kdb=False)
-diff --git a/src/lib/krb5/krb/t_expire_warn.py b/src/lib/krb5/krb/t_expire_warn.py
-index aed39e399..781f2728a 100755
---- a/src/lib/krb5/krb/t_expire_warn.py
-+++ b/src/lib/krb5/krb/t_expire_warn.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- # Copyright (C) 2010 by the Massachusetts Institute of Technology.
- # All rights reserved.
- #
-diff --git a/src/lib/krb5/krb/t_in_ccache_patypes.py b/src/lib/krb5/krb/t_in_ccache_patypes.py
-index c04234064..b2812688c 100755
---- a/src/lib/krb5/krb/t_in_ccache_patypes.py
-+++ b/src/lib/krb5/krb/t_in_ccache_patypes.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- # Copyright (C) 2010,2012 by the Massachusetts Institute of Technology.
- # All rights reserved.
- #
-diff --git a/src/lib/krb5/krb/t_vfy_increds.py b/src/lib/krb5/krb/t_vfy_increds.py
-index c820cc690..b899308a8 100755
---- a/src/lib/krb5/krb/t_vfy_increds.py
-+++ b/src/lib/krb5/krb/t_vfy_increds.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- # Copyright (C) 2011 by the Massachusetts Institute of Technology.
- # All rights reserved.
- #
-diff --git a/src/lib/krb5/os/t_discover_uri.py b/src/lib/krb5/os/t_discover_uri.py
-index 278f98371..87bac1792 100644
---- a/src/lib/krb5/os/t_discover_uri.py
-+++ b/src/lib/krb5/os/t_discover_uri.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- entries = ('URI _kerberos.TEST krb5srv::kkdcp:https://kdc1 1 1\n',
-diff --git a/src/tests/gssapi/t_authind.py b/src/tests/gssapi/t_authind.py
-index 84793beb6..af1741a23 100644
---- a/src/tests/gssapi/t_authind.py
-+++ b/src/tests/gssapi/t_authind.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # Test authentication indicators.  Load the test preauth module so we
-diff --git a/src/tests/gssapi/t_ccselect.py b/src/tests/gssapi/t_ccselect.py
-index 3503f9269..cd62da231 100755
---- a/src/tests/gssapi/t_ccselect.py
-+++ b/src/tests/gssapi/t_ccselect.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- # Copyright (C) 2011 by the Massachusetts Institute of Technology.
- # All rights reserved.
- 
-diff --git a/src/tests/gssapi/t_client_keytab.py b/src/tests/gssapi/t_client_keytab.py
-index 2da87f45b..e474a27c7 100755
---- a/src/tests/gssapi/t_client_keytab.py
-+++ b/src/tests/gssapi/t_client_keytab.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # Set up a basic realm and a client keytab containing two user principals.
-diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py
-index f513db2b5..ee43ff028 100755
---- a/src/tests/gssapi/t_enctypes.py
-+++ b/src/tests/gssapi/t_enctypes.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # Define some convenience abbreviations for enctypes we will see in
-diff --git a/src/tests/gssapi/t_export_cred.py b/src/tests/gssapi/t_export_cred.py
-index b98962788..89167bcc5 100755
---- a/src/tests/gssapi/t_export_cred.py
-+++ b/src/tests/gssapi/t_export_cred.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # Test gss_export_cred and gss_import_cred for initiator creds,
-diff --git a/src/tests/gssapi/t_gssapi.py b/src/tests/gssapi/t_gssapi.py
-index 6da5fceff..a7dda20fb 100755
---- a/src/tests/gssapi/t_gssapi.py
-+++ b/src/tests/gssapi/t_gssapi.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # Test krb5 negotiation under SPNEGO for all enctype configurations.  Also
-diff --git a/src/tests/gssapi/t_s4u.py b/src/tests/gssapi/t_s4u.py
-index e4cd68469..fc9d9e8a4 100755
---- a/src/tests/gssapi/t_s4u.py
-+++ b/src/tests/gssapi/t_s4u.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- realm = K5Realm(create_host=False, get_creds=False)
-diff --git a/src/tests/jsonwalker.py b/src/tests/jsonwalker.py
-index 265c69c70..942ca2db7 100644
---- a/src/tests/jsonwalker.py
-+++ b/src/tests/jsonwalker.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- import sys
- try:
-     import cjson
-diff --git a/src/tests/t_audit.py b/src/tests/t_audit.py
-index 00e96bfea..0f880edb2 100755
---- a/src/tests/t_audit.py
-+++ b/src/tests/t_audit.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- conf = {'plugins': {'audit': {
-diff --git a/src/tests/t_authdata.py b/src/tests/t_authdata.py
-index 8a577b4b1..5cff80348 100644
---- a/src/tests/t_authdata.py
-+++ b/src/tests/t_authdata.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # Load the sample KDC authdata module.
-diff --git a/src/tests/t_bogus_kdc_req.py b/src/tests/t_bogus_kdc_req.py
-index b6208ca68..a101c0e10 100755
---- a/src/tests/t_bogus_kdc_req.py
-+++ b/src/tests/t_bogus_kdc_req.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- import base64
- import socket
- from k5test import *
-diff --git a/src/tests/t_ccache.py b/src/tests/t_ccache.py
-index 61d549b7b..a913eb025 100755
---- a/src/tests/t_ccache.py
-+++ b/src/tests/t_ccache.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- # Copyright (C) 2011 by the Massachusetts Institute of Technology.
- # All rights reserved.
- 
-diff --git a/src/tests/t_certauth.py b/src/tests/t_certauth.py
-index e64a57b0d..9c7094525 100644
---- a/src/tests/t_certauth.py
-+++ b/src/tests/t_certauth.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # Skip this test if pkinit wasn't built.
-diff --git a/src/tests/t_changepw.py b/src/tests/t_changepw.py
-index 37fe4fce1..211cda6c3 100755
---- a/src/tests/t_changepw.py
-+++ b/src/tests/t_changepw.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # This file is intended to cover any password-changing mechanism.  For
-diff --git a/src/tests/t_crossrealm.py b/src/tests/t_crossrealm.py
-index 4d595dca6..09028bfa7 100755
---- a/src/tests/t_crossrealm.py
-+++ b/src/tests/t_crossrealm.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- # Copyright (C) 2011 by the Massachusetts Institute of Technology.
- # All rights reserved.
- #
-diff --git a/src/tests/t_cve-2012-1014.py b/src/tests/t_cve-2012-1014.py
-index e02162d6c..dcff95f6e 100755
---- a/src/tests/t_cve-2012-1014.py
-+++ b/src/tests/t_cve-2012-1014.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- import base64
- import socket
- from k5test import *
-diff --git a/src/tests/t_cve-2012-1015.py b/src/tests/t_cve-2012-1015.py
-index e00c4dc90..28b1e619b 100755
---- a/src/tests/t_cve-2012-1015.py
-+++ b/src/tests/t_cve-2012-1015.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- import base64
- import socket
- from k5test import *
-diff --git a/src/tests/t_cve-2013-1416.py b/src/tests/t_cve-2013-1416.py
-index 94fb6d5ef..8c4391a86 100755
---- a/src/tests/t_cve-2013-1416.py
-+++ b/src/tests/t_cve-2013-1416.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- from k5test import *
- 
- realm = K5Realm()
-diff --git a/src/tests/t_cve-2013-1417.py b/src/tests/t_cve-2013-1417.py
-index c26930a30..ce47d21ca 100755
---- a/src/tests/t_cve-2013-1417.py
-+++ b/src/tests/t_cve-2013-1417.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- from k5test import *
- 
- realm = K5Realm(realm='TEST')
-diff --git a/src/tests/t_dump.py b/src/tests/t_dump.py
-index 8a9462bd8..2cfeada6c 100755
---- a/src/tests/t_dump.py
-+++ b/src/tests/t_dump.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- from filecmp import cmp
- 
-diff --git a/src/tests/t_errmsg.py b/src/tests/t_errmsg.py
-index c9ae6637f..4aacf4e0a 100755
---- a/src/tests/t_errmsg.py
-+++ b/src/tests/t_errmsg.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- realm = K5Realm(create_kdb=False)
-diff --git a/src/tests/t_etype_info.py b/src/tests/t_etype_info.py
-index b2eb0f7af..b12fb53c8 100644
---- a/src/tests/t_etype_info.py
-+++ b/src/tests/t_etype_info.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- supported_enctypes = 'aes128-cts des3-cbc-sha1 rc4-hmac des-cbc-crc:afs3'
-diff --git a/src/tests/t_general.py b/src/tests/t_general.py
-index 91ad0cb8a..96ba8a4b0 100755
---- a/src/tests/t_general.py
-+++ b/src/tests/t_general.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- for realm in multipass_realms(create_host=False):
-diff --git a/src/tests/t_hooks.py b/src/tests/t_hooks.py
-index 58dff3ae7..4fd3822e8 100755
---- a/src/tests/t_hooks.py
-+++ b/src/tests/t_hooks.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # Test that KDC send and recv hooks work correctly.
-diff --git a/src/tests/t_hostrealm.py b/src/tests/t_hostrealm.py
-index 224c067ef..256ba2a38 100755
---- a/src/tests/t_hostrealm.py
-+++ b/src/tests/t_hostrealm.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- plugin = os.path.join(buildtop, "plugins", "hostrealm", "test",
-diff --git a/src/tests/t_iprop.py b/src/tests/t_iprop.py
-index 8e23cd5de..9cbeb3e68 100755
---- a/src/tests/t_iprop.py
-+++ b/src/tests/t_iprop.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- import os
- import re
- 
-diff --git a/src/tests/t_kadm5_auth.py b/src/tests/t_kadm5_auth.py
-index ba4ab8ef1..6e0f42b08 100644
---- a/src/tests/t_kadm5_auth.py
-+++ b/src/tests/t_kadm5_auth.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # Create a realm with the welcomer and bouncer kadm5_auth test modules
-diff --git a/src/tests/t_kadm5_hook.py b/src/tests/t_kadm5_hook.py
-index c1c8c9419..32fab781d 100755
---- a/src/tests/t_kadm5_hook.py
-+++ b/src/tests/t_kadm5_hook.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- plugin = os.path.join(buildtop, "plugins", "kadm5_hook", "test",
-diff --git a/src/tests/t_kadmin_acl.py b/src/tests/t_kadmin_acl.py
-index 42bdf423c..01a3eda29 100755
---- a/src/tests/t_kadmin_acl.py
-+++ b/src/tests/t_kadmin_acl.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- import os
- 
-diff --git a/src/tests/t_kadmin_parsing.py b/src/tests/t_kadmin_parsing.py
-index 8de387c64..bebb01488 100644
---- a/src/tests/t_kadmin_parsing.py
-+++ b/src/tests/t_kadmin_parsing.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # This file contains tests for kadmin command parsing.  Principal
-diff --git a/src/tests/t_kdb.py b/src/tests/t_kdb.py
-index 6e563b103..983cd93c8 100755
---- a/src/tests/t_kdb.py
-+++ b/src/tests/t_kdb.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- import time
- from itertools import imap
-diff --git a/src/tests/t_kdb_locking.py b/src/tests/t_kdb_locking.py
-index aac0a220f..b5afd6d23 100755
---- a/src/tests/t_kdb_locking.py
-+++ b/src/tests/t_kdb_locking.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- # This is a regression test for
- # https://bugzilla.redhat.com/show_bug.cgi?id=586032 .
- #
-diff --git a/src/tests/t_kdc_log.py b/src/tests/t_kdc_log.py
-index 8ddb7691b..1b14828de 100755
---- a/src/tests/t_kdc_log.py
-+++ b/src/tests/t_kdc_log.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- from k5test import *
- 
- # Make a TGS request with an expired ticket.
-diff --git a/src/tests/t_kdcpolicy.py b/src/tests/t_kdcpolicy.py
-index 5b198bb43..a44adfdb5 100644
---- a/src/tests/t_kdcpolicy.py
-+++ b/src/tests/t_kdcpolicy.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- from datetime import datetime
- import re
-diff --git a/src/tests/t_keydata.py b/src/tests/t_keydata.py
-index 5c04a8523..b37233b21 100755
---- a/src/tests/t_keydata.py
-+++ b/src/tests/t_keydata.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- realm = K5Realm(create_user=False, create_host=False)
-diff --git a/src/tests/t_keyrollover.py b/src/tests/t_keyrollover.py
-index bfd38914b..7c8d828f0 100755
---- a/src/tests/t_keyrollover.py
-+++ b/src/tests/t_keyrollover.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- rollover_krb5_conf = {'libdefaults': {'allow_weak_crypto': 'true'}}
-diff --git a/src/tests/t_keytab.py b/src/tests/t_keytab.py
-index a48740ba5..228c36334 100755
---- a/src/tests/t_keytab.py
-+++ b/src/tests/t_keytab.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- for realm in multipass_realms(create_user=False):
-diff --git a/src/tests/t_kprop.py b/src/tests/t_kprop.py
-index 39169675d..f352ec8d7 100755
---- a/src/tests/t_kprop.py
-+++ b/src/tests/t_kprop.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- conf_slave = {'dbmodules': {'db': {'database_name': '$testdir/db.slave'}}}
-diff --git a/src/tests/t_localauth.py b/src/tests/t_localauth.py
-index aa625d038..ebc9cdfde 100755
---- a/src/tests/t_localauth.py
-+++ b/src/tests/t_localauth.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # Unfortunately, we can't reliably test the k5login module.  We can control
-diff --git a/src/tests/t_mkey.py b/src/tests/t_mkey.py
-index 615cd91ca..48a533059 100755
---- a/src/tests/t_mkey.py
-+++ b/src/tests/t_mkey.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- import random
- import re
-diff --git a/src/tests/t_otp.py b/src/tests/t_otp.py
-index 9b18ff94b..0fd35d576 100755
---- a/src/tests/t_otp.py
-+++ b/src/tests/t_otp.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--#
- # Author: Nathaniel McCallum <npmccallum@redhat.com>
- #
- # Copyright (c) 2013 Red Hat, Inc.
-diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
-index 0e964c689..850db4fdd 100755
---- a/src/tests/t_pkinit.py
-+++ b/src/tests/t_pkinit.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # Skip this test if pkinit wasn't built.
-diff --git a/src/tests/t_policy.py b/src/tests/t_policy.py
-index 26c4e466e..eb3865d7c 100755
---- a/src/tests/t_policy.py
-+++ b/src/tests/t_policy.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- import re
- 
-diff --git a/src/tests/t_preauth.py b/src/tests/t_preauth.py
-index 32e35b08b..f597c3d08 100644
---- a/src/tests/t_preauth.py
-+++ b/src/tests/t_preauth.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # Test that the kdcpreauth client_keyblock() callback matches the key
-diff --git a/src/tests/t_princflags.py b/src/tests/t_princflags.py
-index 6378ef94f..aa3660217 100755
---- a/src/tests/t_princflags.py
-+++ b/src/tests/t_princflags.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- from princflags import *
- import re
-diff --git a/src/tests/t_proxy.py b/src/tests/t_proxy.py
-index 4e86fce8f..ff1929bef 100755
---- a/src/tests/t_proxy.py
-+++ b/src/tests/t_proxy.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # Skip this test if we're missing proxy functionality or parts of the proxy.
-@@ -62,7 +61,8 @@ def start_proxy(realm, keycertpem):
-     conf.write('kpasswd = kpasswd://localhost:%d\n' % (realm.portbase + 2))
-     conf.close()
-     realm.env['KDCPROXY_CONFIG'] = proxy_conf_path
--    cmd = [proxy_exec_path, str(realm.server_port()), keycertpem]
-+    cmd = [sys.executable, proxy_exec_path, str(realm.server_port()),
-+           keycertpem]
-     return realm.start_server(cmd, sentinel='proxy server ready')
- 
- # Fail: untrusted issuer and hostname doesn't match.
-diff --git a/src/tests/t_pwqual.py b/src/tests/t_pwqual.py
-index 011110bd1..171805697 100755
---- a/src/tests/t_pwqual.py
-+++ b/src/tests/t_pwqual.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- plugin = os.path.join(buildtop, "plugins", "pwqual", "test", "pwqual_test.so")
-diff --git a/src/tests/t_rdreq.py b/src/tests/t_rdreq.py
-index f67c34866..00cd5cbb4 100755
---- a/src/tests/t_rdreq.py
-+++ b/src/tests/t_rdreq.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- conf = {'realms': {'$realm': {'supported_enctypes': 'aes256-cts aes128-cts'}}}
-diff --git a/src/tests/t_referral.py b/src/tests/t_referral.py
-index e12fdc2e9..2f29d5712 100755
---- a/src/tests/t_referral.py
-+++ b/src/tests/t_referral.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # Create a pair of realms, where KRBTEST1.COM can authenticate to
-diff --git a/src/tests/t_renew.py b/src/tests/t_renew.py
-index 034190c80..67b4182fd 100755
---- a/src/tests/t_renew.py
-+++ b/src/tests/t_renew.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- from datetime import datetime
- import re
-diff --git a/src/tests/t_renprinc.py b/src/tests/t_renprinc.py
-index cc780839a..46cbed441 100755
---- a/src/tests/t_renprinc.py
-+++ b/src/tests/t_renprinc.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- # Copyright (C) 2011 by the Massachusetts Institute of Technology.
- # All rights reserved.
- 
-diff --git a/src/tests/t_salt.py b/src/tests/t_salt.py
-index ddb1905ed..278911a22 100755
---- a/src/tests/t_salt.py
-+++ b/src/tests/t_salt.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- import re
- 
-diff --git a/src/tests/t_sesskeynego.py b/src/tests/t_sesskeynego.py
-index 732c306ea..448092387 100755
---- a/src/tests/t_sesskeynego.py
-+++ b/src/tests/t_sesskeynego.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- import re
- 
-diff --git a/src/tests/t_skew.py b/src/tests/t_skew.py
-index f2ae06695..36d5a95c5 100755
---- a/src/tests/t_skew.py
-+++ b/src/tests/t_skew.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # Create a realm with the KDC one hour in the past.
-diff --git a/src/tests/t_sn2princ.py b/src/tests/t_sn2princ.py
-index 19a0d2fa7..e2c85e665 100755
---- a/src/tests/t_sn2princ.py
-+++ b/src/tests/t_sn2princ.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- offline = (len(args) > 0 and args[0] != "no")
-diff --git a/src/tests/t_spake.py b/src/tests/t_spake.py
-index 5b47e62d3..65af46d18 100644
---- a/src/tests/t_spake.py
-+++ b/src/tests/t_spake.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # The name and number of each supported SPAKE group.
-diff --git a/src/tests/t_stringattr.py b/src/tests/t_stringattr.py
-index 5672a0f20..c2dc348e9 100755
---- a/src/tests/t_stringattr.py
-+++ b/src/tests/t_stringattr.py
-@@ -1,5 +1,3 @@
--#!/usr/bin/python
--
- # Copyright (C) 2011 by the Massachusetts Institute of Technology.
- # All rights reserved.
- 
-diff --git a/src/tests/t_tabdump.py b/src/tests/t_tabdump.py
-index 066e48418..2a86136dd 100755
---- a/src/tests/t_tabdump.py
-+++ b/src/tests/t_tabdump.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- import csv
-diff --git a/src/tests/t_unlockiter.py b/src/tests/t_unlockiter.py
-index 2a438e99a..603cf721d 100755
---- a/src/tests/t_unlockiter.py
-+++ b/src/tests/t_unlockiter.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # Default KDB iteration is locked.  Expect write lock failure unless
-diff --git a/src/tests/t_y2038.py b/src/tests/t_y2038.py
-index 02e946df4..42a4ff7ed 100644
---- a/src/tests/t_y2038.py
-+++ b/src/tests/t_y2038.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- from k5test import *
- 
- # These tests will become much less important after the y2038 boundary
-diff --git a/src/util/paste-kdcproxy.py b/src/util/paste-kdcproxy.py
-index 1e56b8954..30467fd74 100755
---- a/src/util/paste-kdcproxy.py
-+++ b/src/util/paste-kdcproxy.py
-@@ -1,4 +1,3 @@
--#!/usr/bin/python
- import kdcproxy
- from paste import httpserver
- import os
diff --git a/SOURCES/FIPS-aware-SPAKE-group-negotiation.patch b/SOURCES/FIPS-aware-SPAKE-group-negotiation.patch
new file mode 100644
index 0000000..f7bb807
--- /dev/null
+++ b/SOURCES/FIPS-aware-SPAKE-group-negotiation.patch
@@ -0,0 +1,43 @@
+From 5b4467a2c47e6de814e69ec3eb4c3e7a4632119c Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Mon, 1 Apr 2019 13:13:09 -0400
+Subject: [PATCH] FIPS-aware SPAKE group negotiation
+
+(cherry picked from commit 59269fca96168aa89dc32834d188a54eea8953ac)
+---
+ src/plugins/preauth/spake/groups.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/src/plugins/preauth/spake/groups.c b/src/plugins/preauth/spake/groups.c
+index a195cc195..8a913cb5a 100644
+--- a/src/plugins/preauth/spake/groups.c
++++ b/src/plugins/preauth/spake/groups.c
+@@ -56,6 +56,8 @@
+ #include "trace.h"
+ #include "groups.h"
+ 
++#include <openssl/crypto.h>
++
+ #define DEFAULT_GROUPS_CLIENT "edwards25519"
+ #define DEFAULT_GROUPS_KDC ""
+ 
+@@ -102,6 +104,9 @@ find_gdef(int32_t group)
+ {
+     size_t i;
+ 
++    if (group == builtin_edwards25519.reg->id && FIPS_mode())
++        return NULL;
++
+     for (i = 0; groupdefs[i] != NULL; i++) {
+         if (groupdefs[i]->reg->id == group)
+             return groupdefs[i];
+@@ -116,6 +121,9 @@ find_gnum(const char *name)
+ {
+     size_t i;
+ 
++    if (strcasecmp(name, builtin_edwards25519.reg->name) == 0 && FIPS_mode())
++        return 0;
++
+     for (i = 0; groupdefs[i] != NULL; i++) {
+         if (strcasecmp(name, groupdefs[i]->reg->name) == 0)
+             return groupdefs[i]->reg->id;
diff --git a/SOURCES/Fix-SPAKE-memory-leak.patch b/SOURCES/Fix-SPAKE-memory-leak.patch
deleted file mode 100644
index e1cacca..0000000
--- a/SOURCES/Fix-SPAKE-memory-leak.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 390c515e13dffc8c00b44623cba47e27c2f20cf7 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Tue, 27 Mar 2018 10:36:05 -0400
-Subject: [PATCH] Fix SPAKE memory leak
-
-In the NIST group implementations, ossl_fini() needs to free the
-groupdata container as well as its fields.  Also in
-spake_kdc.c:parse_data(), initialize the magic field of the resulting
-data object to avoid a harmless uninitialized memory copy.
-
-ticket: 8647
-(cherry picked from commit 70b88b8018658e052d6eabf06f8fdad17fbe993c)
----
- src/plugins/preauth/spake/openssl.c   | 1 +
- src/plugins/preauth/spake/spake_kdc.c | 1 +
- 2 files changed, 2 insertions(+)
-
-diff --git a/src/plugins/preauth/spake/openssl.c b/src/plugins/preauth/spake/openssl.c
-index b821a9158..f2e4b53ec 100644
---- a/src/plugins/preauth/spake/openssl.c
-+++ b/src/plugins/preauth/spake/openssl.c
-@@ -69,6 +69,7 @@ ossl_fini(groupdata *gd)
-     EC_POINT_free(gd->N);
-     BN_CTX_free(gd->ctx);
-     BN_free(gd->order);
-+    free(gd);
- }
- 
- static krb5_error_code
-diff --git a/src/plugins/preauth/spake/spake_kdc.c b/src/plugins/preauth/spake/spake_kdc.c
-index c1723ebaf..59e88409e 100644
---- a/src/plugins/preauth/spake/spake_kdc.c
-+++ b/src/plugins/preauth/spake/spake_kdc.c
-@@ -75,6 +75,7 @@ parse_data(struct k5input *in, krb5_data *out)
- {
-     out->length = k5_input_get_uint32_be(in);
-     out->data = (char *)k5_input_get_bytes(in, out->length);
-+    out->magic = KV5M_DATA;
- }
- 
- /* Parse a received cookie into its components.  The pointers stored in the
diff --git a/SOURCES/Fix-argument-order-on-strlcpy-in-enctype_name.patch b/SOURCES/Fix-argument-order-on-strlcpy-in-enctype_name.patch
new file mode 100644
index 0000000..9edc3ae
--- /dev/null
+++ b/SOURCES/Fix-argument-order-on-strlcpy-in-enctype_name.patch
@@ -0,0 +1,22 @@
+From 3a64eb3477e0e60d447c99f86b7bf4fd1259cb58 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-hex-conversion-of-PKINIT-certid-strings.patch b/SOURCES/Fix-hex-conversion-of-PKINIT-certid-strings.patch
deleted file mode 100644
index 57d561b..0000000
--- a/SOURCES/Fix-hex-conversion-of-PKINIT-certid-strings.patch
+++ /dev/null
@@ -1,92 +0,0 @@
-From 8b898badbe8051270c6da96f5c15f3bc8b6d974e Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 26 Jan 2018 11:47:50 -0500
-Subject: [PATCH] Fix hex conversion of PKINIT certid strings
-
-When parsing a PKCS11 token specification, correctly convert from hex
-to binary instead of using OpenSSL bignum functions (which would strip
-leading zeros).
-
-[ghudson@mit.edu: made hex_string_to_bin() a bit less verbose; wrote
-commit message]
-
-ticket: 8636
-(cherry picked from commit 63e8b8142fd7b3931a7bf2d6448978ca536bafc0)
----
- .../preauth/pkinit/pkinit_crypto_openssl.c    | 55 +++++++++++++++----
- 1 file changed, 44 insertions(+), 11 deletions(-)
-
-diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
-index 2064eb7bd..eb2953fe1 100644
---- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
-+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
-@@ -4616,6 +4616,43 @@ reassemble_pkcs11_name(pkinit_identity_opts *idopts)
-     return ret;
- }
- 
-+static int
-+hex_string_to_bin(const char *str, int *bin_len_out, CK_BYTE **bin_out)
-+{
-+    size_t str_len, i;
-+    CK_BYTE *bin;
-+    char *endptr, tmp[3] = { '\0', '\0', '\0' };
-+    long val;
-+
-+    *bin_len_out = 0;
-+    *bin_out = NULL;
-+
-+    str_len = strlen(str);
-+    if (str_len % 2 != 0)
-+        return EINVAL;
-+    bin = malloc(str_len / 2);
-+    if (bin == NULL)
-+        return ENOMEM;
-+
-+    errno = 0;
-+    for (i = 0; i < str_len / 2; i++) {
-+        tmp[0] = str[i * 2];
-+        tmp[1] = str[i * 2 + 1];
-+
-+        val = strtol(tmp, &endptr, 16);
-+        if (val < 0 || val > 255 || errno != 0 || endptr != &tmp[2]) {
-+            free(bin);
-+            return EINVAL;
-+        }
-+
-+        bin[i] = (CK_BYTE)val;
-+    }
-+
-+    *bin_len_out = str_len / 2;
-+    *bin_out = bin;
-+    return 0;
-+}
-+
- static krb5_error_code
- pkinit_get_certs_pkcs11(krb5_context context,
-                         pkinit_plg_crypto_context plg_cryptoctx,
-@@ -4658,18 +4695,14 @@ pkinit_get_certs_pkcs11(krb5_context context,
-     }
-     /* Convert the ascii cert_id string into a binary blob */
-     if (idopts->cert_id_string != NULL) {
--        BIGNUM *bn = NULL;
--        BN_hex2bn(&bn, idopts->cert_id_string);
--        if (bn == NULL)
--            return ENOMEM;
--        id_cryptoctx->cert_id_len = BN_num_bytes(bn);
--        id_cryptoctx->cert_id = malloc((size_t) id_cryptoctx->cert_id_len);
--        if (id_cryptoctx->cert_id == NULL) {
--            BN_free(bn);
--            return ENOMEM;
-+        r = hex_string_to_bin(idopts->cert_id_string,
-+                              &id_cryptoctx->cert_id_len,
-+                              &id_cryptoctx->cert_id);
-+        if (r != 0) {
-+            pkiDebug("Failed to convert certid string [%s]\n",
-+                     idopts->cert_id_string);
-+            return r;
-         }
--        BN_bn2bin(bn, id_cryptoctx->cert_id);
--        BN_free(bn);
-     }
-     id_cryptoctx->slotid = idopts->slotid;
-     id_cryptoctx->pkcs11_method = 1;
diff --git a/SOURCES/Fix-k5test-prompts-for-Python-3.patch b/SOURCES/Fix-k5test-prompts-for-Python-3.patch
deleted file mode 100644
index 4adb451..0000000
--- a/SOURCES/Fix-k5test-prompts-for-Python-3.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 43cf653d21d931b792b36c7e6e4cfab3a6236bef Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Wed, 25 Jul 2018 11:50:02 -0400
-Subject: [PATCH] Fix k5test prompts for Python 3
-
-With Python 3, sys.stdout.write() of a partial line followed by
-sys.stdin.readline() does not display the partial line.  Add explicit
-flushes to make prompts visible in k5test.py.
-
-ticket: 8710
-(cherry picked from commit 297535b72177dcced036b78107e9d0e37781c7a3)
----
- src/util/k5test.py | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/src/util/k5test.py b/src/util/k5test.py
-index 81fac3063..e4f99b211 100644
---- a/src/util/k5test.py
-+++ b/src/util/k5test.py
-@@ -457,6 +457,7 @@ def _onexit():
-     if _debug or _stop_before or _stop_after or _shell_before or _shell_after:
-         # Wait before killing daemons in case one is being debugged.
-         sys.stdout.write('*** Press return to kill daemons and exit script: ')
-+        sys.stdout.flush()
-         sys.stdin.readline()
-     for proc in _daemons:
-         os.kill(proc.pid, signal.SIGTERM)
-@@ -658,6 +659,7 @@ def _valgrind(args):
- def _stop_or_shell(stop, shell, env, ind):
-     if (_match_cmdnum(stop, ind)):
-         sys.stdout.write('*** [%d] Waiting for return: ' % ind)
-+        sys.stdout.flush()
-         sys.stdin.readline()
-     if (_match_cmdnum(shell, ind)):
-         output('*** [%d] Spawning shell\n' % ind, True)
diff --git a/SOURCES/Fix-memory-leak-in-none-replay-cache-type.patch b/SOURCES/Fix-memory-leak-in-none-replay-cache-type.patch
new file mode 100644
index 0000000..22e5d59
--- /dev/null
+++ b/SOURCES/Fix-memory-leak-in-none-replay-cache-type.patch
@@ -0,0 +1,34 @@
+From a904a5b85e8425823016b821153b37396edc2306 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-read-overflow-in-KDC-sort_pa_data.patch b/SOURCES/Fix-read-overflow-in-KDC-sort_pa_data.patch
deleted file mode 100644
index 4f46827..0000000
--- a/SOURCES/Fix-read-overflow-in-KDC-sort_pa_data.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From 59a28991e15496e6f9cf867c32dc18e7e1062f59 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Thu, 15 Mar 2018 20:27:30 -0400
-Subject: [PATCH] Fix read overflow in KDC sort_pa_data()
-
-sort_pa_data() could read past the end of pa_order if all preauth
-systems in the table have the PA_REPLACES_KEY flag, causing a
-dereference of preauth_systems[-1].  This situation became possible
-after commit fea1a488924faa3938ef723feaa1ff12d22a91ff with the
-elimination of static_preauth_systems; before that there were always
-table entries which did not have PA_REPLACES_KEY set.
-
-Fix this bug by removing the loop to count n_key_replacers, and
-instead get the count from the prior loop by stopping once we move all
-of the key-replacing modules to the front.
-
-(cherry picked from commit b38e318cea18fd65647189eed64aef83bf1cb772)
----
- src/kdc/kdc_preauth.c | 9 +++++----
- 1 file changed, 5 insertions(+), 4 deletions(-)
-
-diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
-index 80b130222..62ff9a8a7 100644
---- a/src/kdc/kdc_preauth.c
-+++ b/src/kdc/kdc_preauth.c
-@@ -663,17 +663,18 @@ sort_pa_order(krb5_context context, krb5_kdc_req *request, int *pa_order)
-                 break;
-             }
-         }
-+        /* If we didn't find one, we have moved all of the key-replacing
-+         * modules, and i is the count of those modules. */
-+        if (j == n_repliers)
-+            break;
-     }
-+    n_key_replacers = i;
- 
-     if (request->padata != NULL) {
-         /* Now reorder the subset of modules which replace the key,
-          * bubbling those which handle pa_data types provided by the
-          * client ahead of the others.
-          */
--        for (i = 0; preauth_systems[pa_order[i]].flags & PA_REPLACES_KEY; i++) {
--            continue;
--        }
--        n_key_replacers = i;
-         for (i = 0; i < n_key_replacers; i++) {
-             if (pa_list_includes(request->padata,
-                                  preauth_systems[pa_order[i]].type))
diff --git a/SOURCES/Fix-securid_sam2-preauth-for-non-default-salt.patch b/SOURCES/Fix-securid_sam2-preauth-for-non-default-salt.patch
deleted file mode 100644
index 610bf4e..0000000
--- a/SOURCES/Fix-securid_sam2-preauth-for-non-default-salt.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From e405f42b532e377e7e3d654313a07f8c11f48f9a Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Wed, 3 Jan 2018 12:06:08 -0500
-Subject: [PATCH] Fix securid_sam2 preauth for non-default salt
-
-When looking up the client long-term key, look for any salt type, not
-just the default salt type.
-
-ticket: 8629
-(cherry picked from commit a2339099ad13c84de0843fd04d0ba612fc194a1e)
----
- src/plugins/preauth/securid_sam2/grail.c    | 3 +--
- src/plugins/preauth/securid_sam2/securid2.c | 3 +--
- 2 files changed, 2 insertions(+), 4 deletions(-)
-
-diff --git a/src/plugins/preauth/securid_sam2/grail.c b/src/plugins/preauth/securid_sam2/grail.c
-index 18d48f924..48b61b0d1 100644
---- a/src/plugins/preauth/securid_sam2/grail.c
-+++ b/src/plugins/preauth/securid_sam2/grail.c
-@@ -213,8 +213,7 @@ verify_grail_data(krb5_context context, krb5_db_entry *client,
-         return KRB5KDC_ERR_PREAUTH_FAILED;
- 
-     ret = krb5_dbe_find_enctype(context, client,
--                                sr2->sam_enc_nonce_or_sad.enctype,
--                                KRB5_KDB_SALTTYPE_NORMAL,
-+                                sr2->sam_enc_nonce_or_sad.enctype, -1,
-                                 sr2->sam_enc_nonce_or_sad.kvno,
-                                 &client_key_data);
-     if (ret)
-diff --git a/src/plugins/preauth/securid_sam2/securid2.c b/src/plugins/preauth/securid_sam2/securid2.c
-index ca99ce3ef..363e17a10 100644
---- a/src/plugins/preauth/securid_sam2/securid2.c
-+++ b/src/plugins/preauth/securid_sam2/securid2.c
-@@ -313,8 +313,7 @@ verify_securid_data_2(krb5_context context, krb5_db_entry *client,
-     }
- 
-     retval = krb5_dbe_find_enctype(context, client,
--                                   sr2->sam_enc_nonce_or_sad.enctype,
--                                   KRB5_KDB_SALTTYPE_NORMAL,
-+                                   sr2->sam_enc_nonce_or_sad.enctype, -1,
-                                    sr2->sam_enc_nonce_or_sad.kvno,
-                                    &client_key_data);
-     if (retval) {
diff --git a/SOURCES/Fix-segfault-in-finish_dispatch.patch b/SOURCES/Fix-segfault-in-finish_dispatch.patch
deleted file mode 100644
index ff28848..0000000
--- a/SOURCES/Fix-segfault-in-finish_dispatch.patch
+++ /dev/null
@@ -1,133 +0,0 @@
-From 617d153bb32d0bd7db33ccec21043d1113651f3a Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Wed, 18 Apr 2018 14:13:28 -0400
-Subject: [PATCH] Fix segfault in finish_dispatch()
-
-dispatch() doesn't necessarily initialize state->active_realm which
-led to an explicit NULL dereference in finish_dispatch().
-
-Additionally, fix make_too_big_error() so that it won't subsequently
-dereference state->active_realm.
-
-tags: pullup
-target_version: 1.16-next
-target_version: 1.15-next
----
- src/kdc/dispatch.c | 79 ++++++++++++++++++++++++----------------------
- 1 file changed, 42 insertions(+), 37 deletions(-)
-
-diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c
-index 3ed5176a8..fb3686c98 100644
---- a/src/kdc/dispatch.c
-+++ b/src/kdc/dispatch.c
-@@ -35,9 +35,6 @@
- 
- static krb5_int32 last_usec = 0, last_os_random = 0;
- 
--static krb5_error_code make_too_big_error(kdc_realm_t *kdc_active_realm,
--                                          krb5_data **out);
--
- struct dispatch_state {
-     loop_respond_fn respond;
-     void *arg;
-@@ -47,6 +44,41 @@ struct dispatch_state {
-     krb5_context kdc_err_context;
- };
- 
-+
-+static krb5_error_code
-+make_too_big_error(krb5_context context, krb5_principal tgsprinc,
-+                   krb5_data **out)
-+{
-+    krb5_error errpkt;
-+    krb5_error_code retval;
-+    krb5_data *scratch;
-+
-+    *out = NULL;
-+    memset(&errpkt, 0, sizeof(errpkt));
-+
-+    retval = krb5_us_timeofday(context, &errpkt.stime, &errpkt.susec);
-+    if (retval)
-+        return retval;
-+    errpkt.error = KRB_ERR_RESPONSE_TOO_BIG;
-+    errpkt.server = tgsprinc;
-+    errpkt.client = NULL;
-+    errpkt.text.length = 0;
-+    errpkt.text.data = 0;
-+    errpkt.e_data.length = 0;
-+    errpkt.e_data.data = 0;
-+    scratch = malloc(sizeof(*scratch));
-+    if (scratch == NULL)
-+        return ENOMEM;
-+    retval = krb5_mk_error(context, &errpkt, scratch);
-+    if (retval) {
-+        free(scratch);
-+        return retval;
-+    }
-+
-+    *out = scratch;
-+    return 0;
-+}
-+
- static void
- finish_dispatch(struct dispatch_state *state, krb5_error_code code,
-                 krb5_data *response)
-@@ -54,12 +86,17 @@ finish_dispatch(struct dispatch_state *state, krb5_error_code code,
-     loop_respond_fn oldrespond = state->respond;
-     void *oldarg = state->arg;
-     kdc_realm_t *kdc_active_realm = state->active_realm;
-+    krb5_principal tgsprinc = NULL;
-+
-+    if (kdc_active_realm != NULL)
-+        tgsprinc = kdc_active_realm->realm_tgsprinc;
- 
-     if (state->is_tcp == 0 && response &&
-         response->length > (unsigned int)max_dgram_reply_size) {
--        krb5_free_data(kdc_context, response);
-+        krb5_free_data(state->kdc_err_context, response);
-         response = NULL;
--        code = make_too_big_error(kdc_active_realm, &response);
-+        code = make_too_big_error(state->kdc_err_context, tgsprinc,
-+                                  &response);
-         if (code)
-             krb5_klog_syslog(LOG_ERR, "error constructing "
-                              "KRB_ERR_RESPONSE_TOO_BIG error: %s",
-@@ -208,38 +245,6 @@ done:
-     finish_dispatch_cache(state, retval, response);
- }
- 
--static krb5_error_code
--make_too_big_error(kdc_realm_t *kdc_active_realm, krb5_data **out)
--{
--    krb5_error errpkt;
--    krb5_error_code retval;
--    krb5_data *scratch;
--
--    *out = NULL;
--    memset(&errpkt, 0, sizeof(errpkt));
--
--    retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec);
--    if (retval)
--        return retval;
--    errpkt.error = KRB_ERR_RESPONSE_TOO_BIG;
--    errpkt.server = tgs_server;
--    errpkt.client = NULL;
--    errpkt.text.length = 0;
--    errpkt.text.data = 0;
--    errpkt.e_data.length = 0;
--    errpkt.e_data.data = 0;
--    scratch = malloc(sizeof(*scratch));
--    if (scratch == NULL)
--        return ENOMEM;
--    retval = krb5_mk_error(kdc_context, &errpkt, scratch);
--    if (retval) {
--        free(scratch);
--        return retval;
--    }
--
--    *out = scratch;
--    return 0;
--}
- 
- krb5_context get_context(void *handle)
- {
diff --git a/SOURCES/Fix-some-broken-tests-for-Python-3.patch b/SOURCES/Fix-some-broken-tests-for-Python-3.patch
deleted file mode 100644
index 42825b0..0000000
--- a/SOURCES/Fix-some-broken-tests-for-Python-3.patch
+++ /dev/null
@@ -1,81 +0,0 @@
-From eb60404564852a262d4082c3e38086742afb1bd9 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Mon, 16 Jul 2018 16:44:01 -0400
-Subject: [PATCH] Fix some broken tests for Python 3
-
-Remove python2 dependencies in .travis.yml and add python3-paste.
-Convert t_daemon.py and jsonwalker.py to python3.  csjon has no
-python3 version, so replace it with python's built-in JSON module.
-
-python3-pyrad isn't available for Trusty, so krad and OTP tests are
-currently not exercised by Travis.
-
-[ghudson@mit.edu: squashed commits; edited commit message]
-
-ticket: 8710
-(cherry picked from commit d1fb3551c0dff5c3e6555b31fcbf04ff04d577fe)
-[rharwood@redhat.com: .travis.yml]
----
- src/lib/krad/t_daemon.py |  2 +-
- src/tests/jsonwalker.py  | 16 +++++-----------
- 2 files changed, 6 insertions(+), 12 deletions(-)
-
-diff --git a/src/lib/krad/t_daemon.py b/src/lib/krad/t_daemon.py
-index 7d7a5d0c8..7668cd7f8 100755
---- a/src/lib/krad/t_daemon.py
-+++ b/src/lib/krad/t_daemon.py
-@@ -23,7 +23,7 @@
- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- 
--import StringIO
-+from io import StringIO
- import os
- import sys
- import signal
-diff --git a/src/tests/jsonwalker.py b/src/tests/jsonwalker.py
-index 7a0675e08..1880363d2 100644
---- a/src/tests/jsonwalker.py
-+++ b/src/tests/jsonwalker.py
-@@ -1,10 +1,5 @@
- import sys
--try:
--    import cjson
--except ImportError:
--    print("Warning: skipping audit log verification because the cjson module" \
--          " is unavailable")
--    sys.exit(0)
-+import json
- from collections import defaultdict
- from optparse import OptionParser
- 
-@@ -72,7 +67,7 @@ class Parser(object):
-         """
-         Generator that works through dictionary.
-         """
--        for a,v in adict.iteritems():
-+        for a,v in adict.items():
-             if isinstance(v,dict):
-                 for (attrpath,u) in self._walk(v):
-                     yield (a+'.'+attrpath,u)
-@@ -93,17 +88,16 @@ if __name__ == '__main__':
-         with open(options.filename, 'r') as f:
-             content = list()
-             for l in f:
--                content.append(cjson.decode(l.rstrip()))
-+                content.append(json.loads(l.rstrip()))
-         f.close()
-     else:
--        print('Input file in jason format is required')
-+        print('Input file in JSON format is required')
-         exit()
- 
-     defaults = None
-     if options.defaults is not None:
-         with open(options.defaults, 'r') as f:
--            defaults = cjson.decode(f.read())
--        f.close()
-+            defaults = json.load(f)
- 
-     # run test
-     p = Parser(defaults)
diff --git a/SOURCES/Implement-k5_buf_init_dynamic_zap.patch b/SOURCES/Implement-k5_buf_init_dynamic_zap.patch
deleted file mode 100644
index 28fd16b..0000000
--- a/SOURCES/Implement-k5_buf_init_dynamic_zap.patch
+++ /dev/null
@@ -1,149 +0,0 @@
-From 3d651a6e234bed4c4d4865a56c5fa47dab89a5a6 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Mon, 26 Mar 2018 11:12:39 -0400
-Subject: [PATCH] Implement k5_buf_init_dynamic_zap
-
-Add a variant of dynamic k5buf objects which zeroes memory when
-reallocating or freeing the buffer.
-
-(cherry picked from commit 8ee8246c14702dc03b02e31b9fb5b7c2bb674bfb)
----
- src/include/k5-buf.h                          |  6 ++-
- src/util/support/k5buf.c                      | 41 +++++++++++++++----
- src/util/support/libkrb5support-fixed.exports |  1 +
- 3 files changed, 39 insertions(+), 9 deletions(-)
-
-diff --git a/src/include/k5-buf.h b/src/include/k5-buf.h
-index 1223916a6..48e2a7d53 100644
---- a/src/include/k5-buf.h
-+++ b/src/include/k5-buf.h
-@@ -45,7 +45,7 @@
-  */
- 
- /* Buffer type values */
--enum k5buftype { K5BUF_ERROR, K5BUF_FIXED, K5BUF_DYNAMIC };
-+enum k5buftype { K5BUF_ERROR, K5BUF_FIXED, K5BUF_DYNAMIC, K5BUF_DYNAMIC_ZAP };
- 
- struct k5buf {
-     enum k5buftype buftype;
-@@ -63,6 +63,10 @@ void k5_buf_init_fixed(struct k5buf *buf, char *data, size_t space);
- /* Initialize a k5buf using an internally allocated dynamic buffer. */
- void k5_buf_init_dynamic(struct k5buf *buf);
- 
-+/* Initialize a k5buf using an internally allocated dynamic buffer, zeroing
-+ * memory when reallocating or freeing. */
-+void k5_buf_init_dynamic_zap(struct k5buf *buf);
-+
- /* Add a C string to BUF. */
- void k5_buf_add(struct k5buf *buf, const char *data);
- 
-diff --git a/src/util/support/k5buf.c b/src/util/support/k5buf.c
-index 35978f238..b2b5e5b67 100644
---- a/src/util/support/k5buf.c
-+++ b/src/util/support/k5buf.c
-@@ -37,7 +37,7 @@
- /*
-  * Structure invariants:
-  *
-- * buftype is K5BUF_FIXED, K5BUF_DYNAMIC, or K5BUF_ERROR
-+ * buftype is K5BUF_FIXED, K5BUF_DYNAMIC, K5BUF_DYNAMIC_ZAP, or K5BUF_ERROR
-  * if buftype is K5BUF_ERROR, the other fields are NULL or 0
-  * if buftype is not K5BUF_ERROR:
-  *   space > 0
-@@ -77,22 +77,35 @@ ensure_space(struct k5buf *buf, size_t len)
-         return 1;
-     if (buf->buftype == K5BUF_FIXED) /* Can't resize a fixed buffer. */
-         goto error_exit;
--    assert(buf->buftype == K5BUF_DYNAMIC);
-+    assert(buf->buftype == K5BUF_DYNAMIC || buf->buftype == K5BUF_DYNAMIC_ZAP);
-     new_space = buf->space * 2;
-     while (new_space - buf->len - 1 < len) {
-         if (new_space > SIZE_MAX / 2)
-             goto error_exit;
-         new_space *= 2;
-     }
--    new_data = realloc(buf->data, new_space);
--    if (new_data == NULL)
--        goto error_exit;
-+    if (buf->buftype == K5BUF_DYNAMIC_ZAP) {
-+        /* realloc() could leave behind a partial copy of sensitive data. */
-+        new_data = malloc(new_space);
-+        if (new_data == NULL)
-+            goto error_exit;
-+        memcpy(new_data, buf->data, buf->len);
-+        new_data[buf->len] = '\0';
-+        zap(buf->data, buf->len);
-+        free(buf->data);
-+    } else {
-+        new_data = realloc(buf->data, new_space);
-+        if (new_data == NULL)
-+            goto error_exit;
-+    }
-     buf->data = new_data;
-     buf->space = new_space;
-     return 1;
- 
- error_exit:
--    if (buf->buftype == K5BUF_DYNAMIC)
-+    if (buf->buftype == K5BUF_DYNAMIC_ZAP)
-+        zap(buf->data, buf->len);
-+    if (buf->buftype == K5BUF_DYNAMIC_ZAP || buf->buftype == K5BUF_DYNAMIC)
-         free(buf->data);
-     set_error(buf);
-     return 0;
-@@ -123,6 +136,14 @@ k5_buf_init_dynamic(struct k5buf *buf)
-     *endptr(buf) = '\0';
- }
- 
-+void
-+k5_buf_init_dynamic_zap(struct k5buf *buf)
-+{
-+    k5_buf_init_dynamic(buf);
-+    if (buf->buftype == K5BUF_DYNAMIC)
-+        buf->buftype = K5BUF_DYNAMIC_ZAP;
-+}
-+
- void
- k5_buf_add(struct k5buf *buf, const char *data)
- {
-@@ -163,7 +184,7 @@ k5_buf_add_vfmt(struct k5buf *buf, const char *fmt, va_list ap)
-     }
- 
-     /* Optimistically format the data directly into the dynamic buffer. */
--    assert(buf->buftype == K5BUF_DYNAMIC);
-+    assert(buf->buftype == K5BUF_DYNAMIC || buf->buftype == K5BUF_DYNAMIC_ZAP);
-     va_copy(apcopy, ap);
-     r = vsnprintf(endptr(buf), remaining, fmt, apcopy);
-     va_end(apcopy);
-@@ -197,6 +218,8 @@ k5_buf_add_vfmt(struct k5buf *buf, const char *fmt, va_list ap)
-         memcpy(endptr(buf), tmp, r + 1);
-         buf->len += r;
-     }
-+    if (buf->buftype == K5BUF_DYNAMIC_ZAP)
-+        zap(tmp, strlen(tmp));
-     free(tmp);
- }
- 
-@@ -241,7 +264,9 @@ k5_buf_free(struct k5buf *buf)
- {
-     if (buf->buftype == K5BUF_ERROR)
-         return;
--    assert(buf->buftype == K5BUF_DYNAMIC);
-+    assert(buf->buftype == K5BUF_DYNAMIC || buf->buftype == K5BUF_DYNAMIC_ZAP);
-+    if (buf->buftype == K5BUF_DYNAMIC_ZAP)
-+        zap(buf->data, buf->len);
-     free(buf->data);
-     set_error(buf);
- }
-diff --git a/src/util/support/libkrb5support-fixed.exports b/src/util/support/libkrb5support-fixed.exports
-index cb9bf0826..a5e2ade04 100644
---- a/src/util/support/libkrb5support-fixed.exports
-+++ b/src/util/support/libkrb5support-fixed.exports
-@@ -3,6 +3,7 @@ k5_base64_encode
- k5_bcmp
- k5_buf_init_fixed
- k5_buf_init_dynamic
-+k5_buf_init_dynamic_zap
- k5_buf_add
- k5_buf_add_len
- k5_buf_add_fmt
diff --git a/SOURCES/In-FIPS-mode-add-plaintext-fallback-for-RC4-usages-a.patch b/SOURCES/In-FIPS-mode-add-plaintext-fallback-for-RC4-usages-a.patch
index b01f0bc..b2a4f87 100644
--- a/SOURCES/In-FIPS-mode-add-plaintext-fallback-for-RC4-usages-a.patch
+++ b/SOURCES/In-FIPS-mode-add-plaintext-fallback-for-RC4-usages-a.patch
@@ -1,4 +1,4 @@
-From e04d483890496a1747f3cdb20a4df5285147f59b Mon Sep 17 00:00:00 2001
+From 088fd5a56e030739a31a43aee7335bc661a92b1c Mon Sep 17 00:00:00 2001
 From: Robbie Harwood <rharwood@redhat.com>
 Date: Tue, 31 Jul 2018 13:47:26 -0400
 Subject: [PATCH] In FIPS mode, add plaintext fallback for RC4 usages and taint
diff --git a/SOURCES/In-kpropd-debug-log-proper-ticket-enctype-names.patch b/SOURCES/In-kpropd-debug-log-proper-ticket-enctype-names.patch
new file mode 100644
index 0000000..7c83389
--- /dev/null
+++ b/SOURCES/In-kpropd-debug-log-proper-ticket-enctype-names.patch
@@ -0,0 +1,28 @@
+From e07ddc519254a35e54af020643685b9da9e0e973 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
new file mode 100644
index 0000000..51115f6
--- /dev/null
+++ b/SOURCES/In-rd_req_dec-always-log-non-permitted-enctypes.patch
@@ -0,0 +1,54 @@
+From 83c2f0bac35c2ad0872dc9b2a9ca1bdde948f216 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/Include-etype-info-in-for-hardware-preauth-hints.patch b/SOURCES/Include-etype-info-in-for-hardware-preauth-hints.patch
deleted file mode 100644
index 82aba62..0000000
--- a/SOURCES/Include-etype-info-in-for-hardware-preauth-hints.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From bbc68d1657306a61a7646dd7b9690f67705e24be Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Wed, 3 Jan 2018 11:59:14 -0500
-Subject: [PATCH] Include etype-info in for hardware preauth hints
-
-If a principal has the requires_hwauth bit set, include PA-ETYPE-INFO
-or PA-ETYPE-INFO2 padata in the PREAUTH_REQUIRED error, as preauth
-mechs involving hardware tokens may also use the principal's Kerberos
-password.
-
-ticket: 8629
-(cherry picked from commit ba92da05accc524b8037453b63ced1a6c65fd2a1)
----
- src/kdc/kdc_preauth.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
-index 81d0b8cff..739c5e776 100644
---- a/src/kdc/kdc_preauth.c
-+++ b/src/kdc/kdc_preauth.c
-@@ -144,7 +144,7 @@ static preauth_system static_preauth_systems[] = {
-     {
-         "etype-info",
-         KRB5_PADATA_ETYPE_INFO,
--        0,
-+        PA_HARDWARE,
-         NULL,
-         NULL,
-         NULL,
-@@ -155,7 +155,7 @@ static preauth_system static_preauth_systems[] = {
-     {
-         "etype-info2",
-         KRB5_PADATA_ETYPE_INFO2,
--        0,
-+        PA_HARDWARE,
-         NULL,
-         NULL,
-         NULL,
diff --git a/SOURCES/Include-preauth-name-in-trace-output-if-possible.patch b/SOURCES/Include-preauth-name-in-trace-output-if-possible.patch
deleted file mode 100644
index fe88920..0000000
--- a/SOURCES/Include-preauth-name-in-trace-output-if-possible.patch
+++ /dev/null
@@ -1,514 +0,0 @@
-From b623881ec039bffc758f53906f7e4f9b884f1cf4 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Thu, 15 Mar 2018 14:37:28 -0400
-Subject: [PATCH] Include preauth name in trace output if possible
-
-Add a {patype} trace format specifier for a single pa-type value.  Add
-a krb5_preauthtype to string conversion function to trace machinery
-and use it when formatting {patype} or {patypes}.
-
-[ghudson@mit.edu: wrote conversion function; edited commit message]
-
-ticket: 8653 (new)
-(cherry picked from commit 9c68fe39b018666eabe033b639c1f35d03ba51c7)
----
- src/include/k5-trace.h      |  17 +--
- src/lib/krb5/os/t_trace.ref |   2 +-
- src/lib/krb5/os/trace.c     |  61 +++++++++-
- src/tests/t_pkinit.py       |  43 +++----
- src/tests/t_preauth.py      | 216 ++++++++++++++++++------------------
- 5 files changed, 200 insertions(+), 139 deletions(-)
-
-diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
-index 390a8b7d6..5f7eb9517 100644
---- a/src/include/k5-trace.h
-+++ b/src/include/k5-trace.h
-@@ -75,6 +75,7 @@
-  *   {cksum}       const krb5_checksum *, display cksumtype and hex checksum
-  *   {princ}       krb5_principal, unparse and display
-  *   {ptype}       krb5_int32, krb5_principal type, display name
-+ *   {patype}      krb5_preauthtype, a single padata type number
-  *   {patypes}     krb5_pa_data **, display list of padata type numbers
-  *   {etype}       krb5_enctype, display shortest name of enctype
-  *   {etypes}      krb5_enctype *, display list of enctypes
-@@ -232,14 +233,14 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
- #define TRACE_INIT_CREDS_PREAUTH_DECRYPT_FAIL(c, code)                  \
-     TRACE(c, "Decrypt with preauth AS key failed: {kerr}", code)
- #define TRACE_INIT_CREDS_PREAUTH_MORE(c, patype)                \
--    TRACE(c, "Continuing preauth mech {int}", (int)patype)
-+    TRACE(c, "Continuing preauth mech {patype}", patype)
- #define TRACE_INIT_CREDS_PREAUTH_NONE(c)        \
-     TRACE(c, "Sending unauthenticated request")
- #define TRACE_INIT_CREDS_PREAUTH_OPTIMISTIC(c)  \
-     TRACE(c, "Attempting optimistic preauth")
- #define TRACE_INIT_CREDS_PREAUTH_TRYAGAIN(c, patype, code)              \
--    TRACE(c, "Recovering from KDC error {int} using preauth mech {int}", \
--          (int)patype, (int)code)
-+    TRACE(c, "Recovering from KDC error {int} using preauth mech {patype}", \
-+          patype, (int)code)
- #define TRACE_INIT_CREDS_RESTART_FAST(c)        \
-     TRACE(c, "Restarting to upgrade to FAST")
- #define TRACE_INIT_CREDS_RESTART_PREAUTH_FAILED(c)                      \
-@@ -290,7 +291,7 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
- 
- #define TRACE_PREAUTH_CONFLICT(c, name1, name2, patype)                 \
-     TRACE(c, "Preauth module {str} conflicts with module {str} for pa " \
--          "type {int}", name1, name2, (int) patype)
-+          "type {patype}", name1, name2, patype)
- #define TRACE_PREAUTH_COOKIE(c, len, data)                      \
-     TRACE(c, "Received cookie: {lenstr}", (size_t) len, data)
- #define TRACE_PREAUTH_ENC_TS_KEY_GAK(c, keyblock)                       \
-@@ -302,8 +303,8 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
-     TRACE(c, "Selected etype info: etype {etype}, salt \"{data}\", " \
-           "params \"{data}\"", etype, salt, s2kparams)
- #define TRACE_PREAUTH_INFO_FAIL(c, patype, code)                        \
--    TRACE(c, "Preauth builtin info function failure, type={int}: {kerr}", \
--          (int) patype, code)
-+    TRACE(c, "Preauth builtin info function failure, type={patype}: {kerr}", \
-+          patype, code)
- #define TRACE_PREAUTH_INPUT(c, padata)                          \
-     TRACE(c, "Processing preauth types: {patypes}", padata)
- #define TRACE_PREAUTH_OUTPUT(c, padata)                                 \
-@@ -314,8 +315,8 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
- #define TRACE_PREAUTH_SAM_KEY_GAK(c, keyblock)                  \
-     TRACE(c, "AS key obtained for SAM: {keyblock}", keyblock)
- #define TRACE_PREAUTH_SALT(c, salt, patype)                          \
--    TRACE(c, "Received salt \"{data}\" via padata type {int}", salt, \
--          (int) patype)
-+    TRACE(c, "Received salt \"{data}\" via padata type {patype}", salt, \
-+          patype)
- #define TRACE_PREAUTH_SKIP(c, name, patype)                           \
-     TRACE(c, "Skipping previously used preauth module {str} ({int})", \
-           name, (int) patype)
-diff --git a/src/lib/krb5/os/t_trace.ref b/src/lib/krb5/os/t_trace.ref
-index ca5818a1e..bd5d9b6b6 100644
---- a/src/lib/krb5/os/t_trace.ref
-+++ b/src/lib/krb5/os/t_trace.ref
-@@ -38,7 +38,7 @@ int, krb5_principal type: Windows 2000 UPN and SID
- int, krb5_principal type: NT 4 style name
- int, krb5_principal type: NT 4 style name and SID
- int, krb5_principal type: ?
--krb5_pa_data **, display list of padata type numbers: 3, 0
-+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: des-cbc-crc
- krb5_enctype *, display list of enctypes: 5, rc4-hmac-exp, 511
-diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
-index 779f184cb..10b4f0c14 100644
---- a/src/lib/krb5/os/trace.c
-+++ b/src/lib/krb5/os/trace.c
-@@ -123,6 +123,50 @@ principal_type_string(krb5_int32 type)
-     }
- }
- 
-+static char *
-+padata_type_string(krb5_preauthtype type)
-+{
-+    switch (type) {
-+    case KRB5_PADATA_TGS_REQ: return "PA-TGS-REQ";
-+    case KRB5_PADATA_ENC_TIMESTAMP: return "PA-ENC-TIMESTAMP";
-+    case KRB5_PADATA_PW_SALT: return "PA-PW-SALT";
-+    case KRB5_PADATA_ENC_UNIX_TIME: return "PA-ENC-UNIX-TIME";
-+    case KRB5_PADATA_ENC_SANDIA_SECURID: return "PA-SANDIA-SECUREID";
-+    case KRB5_PADATA_SESAME: return "PA-SESAME";
-+    case KRB5_PADATA_OSF_DCE: return "PA-OSF-DCE";
-+    case KRB5_CYBERSAFE_SECUREID: return "PA-CYBERSAFE-SECUREID";
-+    case KRB5_PADATA_AFS3_SALT: return "PA-AFS3-SALT";
-+    case KRB5_PADATA_ETYPE_INFO: return "PA-ETYPE-INFO";
-+    case KRB5_PADATA_SAM_CHALLENGE: return "PA-SAM-CHALLENGE";
-+    case KRB5_PADATA_SAM_RESPONSE: return "PA-SAM-RESPONSE";
-+    case KRB5_PADATA_PK_AS_REQ_OLD: return "PA-PK-AS-REQ_OLD";
-+    case KRB5_PADATA_PK_AS_REP_OLD: return "PA-PK-AS-REP_OLD";
-+    case KRB5_PADATA_PK_AS_REQ: return "PA-PK-AS-REQ";
-+    case KRB5_PADATA_PK_AS_REP: return "PA-PK-AS-REP";
-+    case KRB5_PADATA_ETYPE_INFO2: return "PA-ETYPE-INFO2";
-+    case KRB5_PADATA_SVR_REFERRAL_INFO: return "PA-SVR-REFERRAL-INFO";
-+    case KRB5_PADATA_SAM_REDIRECT: return "PA-SAM-REDIRECT";
-+    case KRB5_PADATA_GET_FROM_TYPED_DATA: return "PA-GET-FROM-TYPED-DATA";
-+    case KRB5_PADATA_SAM_CHALLENGE_2: return "PA-SAM-CHALLENGE2";
-+    case KRB5_PADATA_SAM_RESPONSE_2: return "PA-SAM-RESPONSE2";
-+    case KRB5_PADATA_PAC_REQUEST: return "PA-PAC-REQUEST";
-+    case KRB5_PADATA_FOR_USER: return "PA-FOR_USER";
-+    case KRB5_PADATA_S4U_X509_USER: return "PA-FOR-X509-USER";
-+    case KRB5_PADATA_AS_CHECKSUM: return "PA-AS-CHECKSUM";
-+    case KRB5_PADATA_FX_COOKIE: return "PA-FX-COOKIE";
-+    case KRB5_PADATA_FX_FAST: return "PA-FX-FAST";
-+    case KRB5_PADATA_FX_ERROR: return "PA-FX-ERROR";
-+    case KRB5_PADATA_ENCRYPTED_CHALLENGE: return "PA-ENCRYPTED-CHALLENGE";
-+    case KRB5_PADATA_OTP_CHALLENGE: return "PA-OTP-CHALLENGE";
-+    case KRB5_PADATA_OTP_REQUEST: return "PA-OTP-REQUEST";
-+    case KRB5_PADATA_OTP_PIN_CHANGE: return "PA-OTP-PIN-CHANGE";
-+    case KRB5_PADATA_PKINIT_KX: return "PA-PKINIT-KX";
-+    case KRB5_ENCPADATA_REQ_ENC_PA_REP: return "PA-REQ-ENC-PA-REP";
-+    case KRB5_PADATA_AS_FRESHNESS: return "PA_AS_FRESHNESS";
-+    default: return NULL;
-+    }
-+}
-+
- static char *
- trace_format(krb5_context context, const char *fmt, va_list ap)
- {
-@@ -140,6 +184,8 @@ trace_format(krb5_context context, const char *fmt, va_list ap)
-     krb5_key key;
-     const krb5_checksum *cksum;
-     krb5_pa_data **padata;
-+    krb5_preauthtype pa_type;
-+    const char *name;
-     krb5_ccache ccache;
-     krb5_keytab keytab;
-     krb5_creds *creds;
-@@ -271,10 +317,23 @@ trace_format(krb5_context context, const char *fmt, va_list ap)
-             if (padata == NULL || *padata == NULL)
-                 k5_buf_add(&buf, "(empty)");
-             for (; padata != NULL && *padata != NULL; padata++) {
--                k5_buf_add_fmt(&buf, "%d", (int)(*padata)->pa_type);
-+                pa_type = (*padata)->pa_type;
-+                name = padata_type_string(pa_type);
-+                if (name != NULL)
-+                    k5_buf_add_fmt(&buf, "%s (%d)", name, (int)pa_type);
-+                else
-+                    k5_buf_add_fmt(&buf, "%d", (int)pa_type);
-+
-                 if (*(padata + 1) != NULL)
-                     k5_buf_add(&buf, ", ");
-             }
-+        } else if (strcmp(tmpbuf, "patype") == 0) {
-+            pa_type = va_arg(ap, krb5_preauthtype);
-+            name = padata_type_string(pa_type);
-+            if (name != NULL)
-+                k5_buf_add_fmt(&buf, "%s (%d)", name, (int)pa_type);
-+            else
-+                k5_buf_add_fmt(&buf, "%d", (int)pa_type);
-         } else if (strcmp(tmpbuf, "etype") == 0) {
-             etype = va_arg(ap, krb5_enctype);
-             if (krb5_enctype_to_name(etype, TRUE, tmpbuf, sizeof(tmpbuf)) == 0)
-diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
-index 5bc60cb1e..0e964c689 100755
---- a/src/tests/t_pkinit.py
-+++ b/src/tests/t_pkinit.py
-@@ -164,18 +164,19 @@ realm.stop_kdc()
- realm.start_kdc()
- 
- # Run the basic test - PKINIT with FILE: identity, with no password on the key.
-+msgs = ('Sending unauthenticated request',
-+        '/Additional pre-authentication required',
-+        'Preauthenticating using KDC method data',
-+        'PKINIT client received freshness token from KDC',
-+        'PKINIT loading CA certs and CRLs from FILE',
-+        'PKINIT client making DH request',
-+        ' preauth for next request: PA-FX-COOKIE (133), PA-PK-AS-REQ (16)',
-+        'PKINIT client verified DH reply',
-+        'PKINIT client found id-pkinit-san in KDC cert',
-+        'PKINIT client matched KDC principal krbtgt/')
- realm.kinit(realm.user_princ,
-             flags=['-X', 'X509_user_identity=%s' % file_identity],
--            expected_trace=('Sending unauthenticated request',
--                            '/Additional pre-authentication required',
--                            'Preauthenticating using KDC method data',
--                            'PKINIT client received freshness token from KDC',
--                            'PKINIT loading CA certs and CRLs from FILE',
--                            'PKINIT client making DH request',
--                            'Produced preauth for next request: 133, 16',
--                            'PKINIT client verified DH reply',
--                            'PKINIT client found id-pkinit-san in KDC cert',
--                            'PKINIT client matched KDC principal krbtgt/'))
-+            expected_trace=msgs)
- realm.klist(realm.user_princ)
- realm.run([kvno, realm.host_princ])
- 
-@@ -194,19 +195,19 @@ minbits_kdc_conf = {'realms': {'$realm': {'pkinit_dh_min_bits': '4096'}}}
- minbits_env = realm.special_env('restrict', True, kdc_conf=minbits_kdc_conf)
- realm.stop_kdc()
- realm.start_kdc(env=minbits_env)
--expected_trace = ('Sending unauthenticated request',
--                  '/Additional pre-authentication required',
--                  'Preauthenticating using KDC method data',
--                  'Preauth module pkinit (16) (real) returned: 0/Success',
--                  'Produced preauth for next request: 133, 16',
--                  '/Key parameters not accepted',
--                  'Preauth tryagain input types (16): 109, 133',
--                  'trying again with KDC-provided parameters',
--                  'Preauth module pkinit (16) tryagain returned: 0/Success',
--                  'Followup preauth for next request: 16, 133')
-+msgs = ('Sending unauthenticated request',
-+        '/Additional pre-authentication required',
-+        'Preauthenticating using KDC method data',
-+        'Preauth module pkinit (16) (real) returned: 0/Success',
-+        ' preauth for next request: PA-FX-COOKIE (133), PA-PK-AS-REQ (16)',
-+        '/Key parameters not accepted',
-+        'Preauth tryagain input types (16): 109, PA-FX-COOKIE (133)',
-+        'trying again with KDC-provided parameters',
-+        'Preauth module pkinit (16) tryagain returned: 0/Success',
-+        ' preauth for next request: PA-PK-AS-REQ (16), PA-FX-COOKIE (133)')
- realm.kinit(realm.user_princ,
-             flags=['-X', 'X509_user_identity=%s' % file_identity],
--            expected_trace=expected_trace)
-+            expected_trace=msgs)
- 
- # Test enforcement of required freshness tokens.  (We can leave
- # freshness tokens required after this test.)
-diff --git a/src/tests/t_preauth.py b/src/tests/t_preauth.py
-index fec0bf619..efb3ea20d 100644
---- a/src/tests/t_preauth.py
-+++ b/src/tests/t_preauth.py
-@@ -18,15 +18,15 @@ realm.kinit('nokeyuser', password('user'), expected_code=1,
- # PA-FX-COOKIE; 2 is encrypted timestamp.
- 
- # Test normal preauth flow.
--expected_trace = ('Sending unauthenticated request',
--                  '/Additional pre-authentication required',
--                  'Preauthenticating using KDC method data',
--                  'Processing preauth types:',
--                  'Preauth module test (-123) (real) returned: 0/Success',
--                  'Produced preauth for next request: 133, -123',
--                  'Decrypted AS reply')
-+msgs = ('Sending unauthenticated request',
-+        '/Additional pre-authentication required',
-+        'Preauthenticating using KDC method data',
-+        'Processing preauth types:',
-+        'Preauth module test (-123) (real) returned: 0/Success',
-+        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
-+        'Decrypted AS reply')
- realm.run(['./icred', realm.user_princ, password('user')],
--          expected_msg='testval', expected_trace=expected_trace)
-+          expected_msg='testval', expected_trace=msgs)
- 
- # Test successful optimistic preauth.
- expected_trace = ('Attempting optimistic preauth',
-@@ -39,136 +39,136 @@ realm.run(['./icred', '-o', '-123', realm.user_princ, password('user')],
- 
- # Test optimistic preauth failing on client, followed by successful
- # preauth using the same module.
--expected_trace = ('Attempting optimistic preauth',
--                  'Processing preauth types: -123',
--                  '/induced optimistic fail',
--                  'Sending unauthenticated request',
--                  '/Additional pre-authentication required',
--                  'Preauthenticating using KDC method data',
--                  'Processing preauth types:',
--                  'Preauth module test (-123) (real) returned: 0/Success',
--                  'Produced preauth for next request: 133, -123',
--                  'Decrypted AS reply')
-+msgs = ('Attempting optimistic preauth',
-+        'Processing preauth types: -123',
-+        '/induced optimistic fail',
-+        'Sending unauthenticated request',
-+        '/Additional pre-authentication required',
-+        'Preauthenticating using KDC method data',
-+        'Processing preauth types:',
-+        'Preauth module test (-123) (real) returned: 0/Success',
-+        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
-+        'Decrypted AS reply')
- realm.run(['./icred', '-o', '-123', '-X', 'fail_optimistic', realm.user_princ,
-            password('user')], expected_msg='testval',
--          expected_trace=expected_trace)
-+          expected_trace=msgs)
- 
- # Test optimistic preauth failing on KDC, followed by successful preauth
- # using the same module.
- realm.run([kadminl, 'setstr', realm.user_princ, 'failopt', 'yes'])
--expected_trace = ('Attempting optimistic preauth',
--                  'Processing preauth types: -123',
--                  'Preauth module test (-123) (real) returned: 0/Success',
--                  'Produced preauth for next request: -123',
--                  '/Preauthentication failed',
--                  'Preauthenticating using KDC method data',
--                  'Processing preauth types:',
--                  'Preauth module test (-123) (real) returned: 0/Success',
--                  'Produced preauth for next request: 133, -123',
--                  'Decrypted AS reply')
-+msgs = ('Attempting optimistic preauth',
-+        'Processing preauth types: -123',
-+        'Preauth module test (-123) (real) returned: 0/Success',
-+        'Produced preauth for next request: -123',
-+        '/Preauthentication failed',
-+        'Preauthenticating using KDC method data',
-+        'Processing preauth types:',
-+        'Preauth module test (-123) (real) returned: 0/Success',
-+        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
-+        'Decrypted AS reply')
- realm.run(['./icred', '-o', '-123', realm.user_princ, password('user')],
--          expected_msg='testval', expected_trace=expected_trace)
-+          expected_msg='testval', expected_trace=msgs)
- realm.run([kadminl, 'delstr', realm.user_princ, 'failopt'])
- 
- # Test KDC_ERR_MORE_PREAUTH_DATA_REQUIRED and secure cookies.
- realm.run([kadminl, 'setstr', realm.user_princ, '2rt', 'secondtrip'])
--expected_trace = ('Sending unauthenticated request',
--                  '/Additional pre-authentication required',
--                  'Preauthenticating using KDC method data',
--                  'Processing preauth types:',
--                  'Preauth module test (-123) (real) returned: 0/Success',
--                  'Produced preauth for next request: 133, -123',
--                  '/More preauthentication data is required',
--                  'Continuing preauth mech -123',
--                  'Processing preauth types: -123, 133',
--                  'Produced preauth for next request: 133, -123',
--                  'Decrypted AS reply')
-+msgs = ('Sending unauthenticated request',
-+        '/Additional pre-authentication required',
-+        'Preauthenticating using KDC method data',
-+        'Processing preauth types:',
-+        'Preauth module test (-123) (real) returned: 0/Success',
-+        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
-+        '/More preauthentication data is required',
-+        'Continuing preauth mech -123',
-+        'Processing preauth types: -123, PA-FX-COOKIE (133)',
-+        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
-+        'Decrypted AS reply')
- realm.run(['./icred', realm.user_princ, password('user')],
--          expected_msg='2rt: secondtrip', expected_trace=expected_trace)
-+          expected_msg='2rt: secondtrip', expected_trace=msgs)
- 
- # Test client-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED,
- # falling back to encrypted timestamp.
--expected_trace = ('Sending unauthenticated request',
--                  '/Additional pre-authentication required',
--                  'Preauthenticating using KDC method data',
--                  'Processing preauth types:',
--                  'Preauth module test (-123) (real) returned: 0/Success',
--                  'Produced preauth for next request: 133, -123',
--                  '/More preauthentication data is required',
--                  'Continuing preauth mech -123',
--                  'Processing preauth types: -123, 133',
--                  '/induced 2rt fail',
--                  'Preauthenticating using KDC method data',
--                  'Processing preauth types:',
--                  'Encrypted timestamp (for ',
--                  'module encrypted_timestamp (2) (real) returned: 0/Success',
--                  'Produced preauth for next request: 133, 2',
--                  'Decrypted AS reply')
-+msgs = ('Sending unauthenticated request',
-+        '/Additional pre-authentication required',
-+        'Preauthenticating using KDC method data',
-+        'Processing preauth types:',
-+        'Preauth module test (-123) (real) returned: 0/Success',
-+        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
-+        '/More preauthentication data is required',
-+        'Continuing preauth mech -123',
-+        'Processing preauth types: -123, PA-FX-COOKIE (133)',
-+        '/induced 2rt fail',
-+        'Preauthenticating using KDC method data',
-+        'Processing preauth types:',
-+        'Encrypted timestamp (for ',
-+        'module encrypted_timestamp (2) (real) returned: 0/Success',
-+        'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)',
-+        'Decrypted AS reply')
- realm.run(['./icred', '-X', 'fail_2rt', realm.user_princ, password('user')],
--          expected_msg='2rt: secondtrip', expected_trace=expected_trace)
-+          expected_msg='2rt: secondtrip', expected_trace=msgs)
- 
- # Test KDC-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED,
- # falling back to encrypted timestamp.
- realm.run([kadminl, 'setstr', realm.user_princ, 'fail2rt', 'yes'])
--expected_trace = ('Sending unauthenticated request',
--                  '/Additional pre-authentication required',
--                  'Preauthenticating using KDC method data',
--                  'Processing preauth types:',
--                  'Preauth module test (-123) (real) returned: 0/Success',
--                  'Produced preauth for next request: 133, -123',
--                  '/More preauthentication data is required',
--                  'Continuing preauth mech -123',
--                  'Processing preauth types: -123, 133',
--                  'Preauth module test (-123) (real) returned: 0/Success',
--                  'Produced preauth for next request: 133, -123',
--                  '/Preauthentication failed',
--                  'Preauthenticating using KDC method data',
--                  'Processing preauth types:',
--                  'Encrypted timestamp (for ',
--                  'module encrypted_timestamp (2) (real) returned: 0/Success',
--                  'Produced preauth for next request: 133, 2',
--                  'Decrypted AS reply')
-+msgs = ('Sending unauthenticated request',
-+        '/Additional pre-authentication required',
-+        'Preauthenticating using KDC method data',
-+        'Processing preauth types:',
-+        'Preauth module test (-123) (real) returned: 0/Success',
-+        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
-+        '/More preauthentication data is required',
-+        'Continuing preauth mech -123',
-+        'Processing preauth types: -123, PA-FX-COOKIE (133)',
-+        'Preauth module test (-123) (real) returned: 0/Success',
-+        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
-+        '/Preauthentication failed',
-+        'Preauthenticating using KDC method data',
-+        'Processing preauth types:',
-+        'Encrypted timestamp (for ',
-+        'module encrypted_timestamp (2) (real) returned: 0/Success',
-+        'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)',
-+        'Decrypted AS reply')
- realm.run(['./icred', realm.user_princ, password('user')],
--          expected_msg='2rt: secondtrip', expected_trace=expected_trace)
-+          expected_msg='2rt: secondtrip', expected_trace=msgs)
- realm.run([kadminl, 'delstr', realm.user_princ, 'fail2rt'])
- 
- # Test tryagain flow by inducing a KDC_ERR_ENCTYPE_NOSUPP error on the KDC.
- realm.run([kadminl, 'setstr', realm.user_princ, 'err', 'testagain'])
--expected_trace = ('Sending unauthenticated request',
--                  '/Additional pre-authentication required',
--                  'Preauthenticating using KDC method data',
--                  'Processing preauth types:',
--                  'Preauth module test (-123) (real) returned: 0/Success',
--                  'Produced preauth for next request: 133, -123',
--                  '/KDC has no support for encryption type',
--                  'Recovering from KDC error 14 using preauth mech -123',
--                  'Preauth tryagain input types (-123): -123, 133',
--                  'Preauth module test (-123) tryagain returned: 0/Success',
--                  'Followup preauth for next request: -123, 133',
--                  'Decrypted AS reply')
-+msgs = ('Sending unauthenticated request',
-+        '/Additional pre-authentication required',
-+        'Preauthenticating using KDC method data',
-+        'Processing preauth types:',
-+        'Preauth module test (-123) (real) returned: 0/Success',
-+        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
-+        '/KDC has no support for encryption type',
-+        'Recovering from KDC error 14 using preauth mech -123',
-+        'Preauth tryagain input types (-123): -123, PA-FX-COOKIE (133)',
-+        'Preauth module test (-123) tryagain returned: 0/Success',
-+        'Followup preauth for next request: -123, PA-FX-COOKIE (133)',
-+        'Decrypted AS reply')
- realm.run(['./icred', realm.user_princ, password('user')],
--          expected_msg='tryagain: testagain', expected_trace=expected_trace)
-+          expected_msg='tryagain: testagain', expected_trace=msgs)
- 
- # Test a client-side tryagain failure, falling back to encrypted
- # timestamp.
--expected_trace = ('Sending unauthenticated request',
--                  '/Additional pre-authentication required',
--                  'Preauthenticating using KDC method data',
--                  'Processing preauth types:',
--                  'Preauth module test (-123) (real) returned: 0/Success',
--                  'Produced preauth for next request: 133, -123',
--                  '/KDC has no support for encryption type',
--                  'Recovering from KDC error 14 using preauth mech -123',
--                  'Preauth tryagain input types (-123): -123, 133',
--                  '/induced tryagain fail',
--                  'Preauthenticating using KDC method data',
--                  'Processing preauth types:',
--                  'Encrypted timestamp (for ',
--                  'module encrypted_timestamp (2) (real) returned: 0/Success',
--                  'Produced preauth for next request: 133, 2',
--                  'Decrypted AS reply')
-+msgs = ('Sending unauthenticated request',
-+        '/Additional pre-authentication required',
-+        'Preauthenticating using KDC method data',
-+        'Processing preauth types:',
-+        'Preauth module test (-123) (real) returned: 0/Success',
-+        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
-+        '/KDC has no support for encryption type',
-+        'Recovering from KDC error 14 using preauth mech -123',
-+        'Preauth tryagain input types (-123): -123, PA-FX-COOKIE (133)',
-+        '/induced tryagain fail',
-+        'Preauthenticating using KDC method data',
-+        'Processing preauth types:',
-+        'Encrypted timestamp (for ',
-+        'module encrypted_timestamp (2) (real) returned: 0/Success',
-+        'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)',
-+        'Decrypted AS reply')
- realm.run(['./icred', '-X', 'fail_tryagain', realm.user_princ,
--           password('user')], expected_trace=expected_trace)
-+           password('user')], expected_trace=msgs)
- 
- # Test that multiple stepwise initial creds operations can be
- # performed with the same krb5_context, with proper tracking of
diff --git a/SOURCES/Log-when-non-root-ksu-authorization-fails.patch b/SOURCES/Log-when-non-root-ksu-authorization-fails.patch
deleted file mode 100644
index 704b5a9..0000000
--- a/SOURCES/Log-when-non-root-ksu-authorization-fails.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 9dd3a84f324979c29e8ab4b472e98dfa73e6b290 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Mon, 7 May 2018 16:42:59 -0400
-Subject: [PATCH] Log when non-root ksu authorization fails
-
-If non-root user attempts to ksu but is denied by policy, log to
-syslog at LOG_WARNING in keeping with other failure messages.
-
-ticket: 8270
-(cherry picked from commit 6cfa5c113e981f14f70ccafa20abfa5c46b665ba)
----
- src/clients/ksu/main.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
-diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c
-index c6321c01b..35ff8978f 100644
---- a/src/clients/ksu/main.c
-+++ b/src/clients/ksu/main.c
-@@ -417,6 +417,16 @@ main (argc, argv)
-     if (hp){
-         if (gb_err) fprintf(stderr, "%s", gb_err);
-         fprintf(stderr, _("account %s: authorization failed\n"), target_user);
-+
-+        if (cmd != NULL) {
-+            syslog(LOG_WARNING,
-+                   "Account %s: authorization for %s for execution of %s failed",
-+                   target_user, source_user, cmd);
-+        } else {
-+            syslog(LOG_WARNING, "Account %s: authorization of %s failed",
-+                   target_user, source_user);
-+        }
-+
-         exit(1);
-     }
- 
diff --git a/SOURCES/Make-docs-build-python3-compatible.patch b/SOURCES/Make-docs-build-python3-compatible.patch
deleted file mode 100644
index 58a3e86..0000000
--- a/SOURCES/Make-docs-build-python3-compatible.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-From 16c745b7e9e239535a8c71dc7022b477a5165e01 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Wed, 13 Jun 2018 15:07:48 -0400
-Subject: [PATCH] Make docs build python3-compatible
-
-python3 removed execfile(), which we use for loading version data and
-paths information in docs.  Call exec() directly instead.
-
-ticket: 8692 (new)
-(cherry picked from commit a7c6d98480f1e33454173f88381921472d72f80a)
----
- doc/conf.py | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/doc/conf.py b/doc/conf.py
-index 25ba214a8..0555808e6 100644
---- a/doc/conf.py
-+++ b/doc/conf.py
-@@ -50,7 +50,7 @@ copyright = u'1985-2018, MIT'
- # The version info for the project you're documenting, acts as replacement for
- # |version| and |release|, also used in various other places throughout the
- # built documents.
--execfile("version.py")
-+exec(open("version.py").read())
- # The short X.Y version.
- r_list = [r_major, r_minor]
- if r_patch:
-@@ -238,7 +238,7 @@ if 'mansubs' in tags:
-     ckeytab = '``@CKTNAME@``'
- elif 'pathsubs' in tags:
-     # Read configured paths from a file produced by the build system.
--    execfile('paths.py')
-+    exec(open("paths.py").read())
- else:
-     bindir = ':ref:`BINDIR <paths>`'
-     sbindir = ':ref:`SBINDIR <paths>`'
diff --git a/SOURCES/Make-etype-names-in-KDC-logs-human-readable.patch b/SOURCES/Make-etype-names-in-KDC-logs-human-readable.patch
new file mode 100644
index 0000000..b2e21f3
--- /dev/null
+++ b/SOURCES/Make-etype-names-in-KDC-logs-human-readable.patch
@@ -0,0 +1,293 @@
+From c3dd133cf06d55e3fe516a2aa8b4b37e203878da 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 | 125 +++++++++++++++++++++++----------------------
+ src/kdc/kdc_util.h |   6 +--
+ 3 files changed, 87 insertions(+), 86 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))
++/* 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)
++{
++    char *name;
++
++    if (buflen == 0)
++        return EINVAL;
++    *buf = '\0'; /* ensure these are always valid C-strings */
++
++    /* 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);
+ 
+-/*
+- * 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)
++    if (strlcpy(name, buf, buflen) >= buflen)
++        return ENOMEM;
++    return 0;
++}
+ 
+-void
+-ktypes2str(char *s, size_t len, int nktypes, krb5_enctype *ktype)
++char *
++ktypes2str(krb5_enctype *ktype, int nktypes)
+ {
++    struct k5buf buf;
+     int i;
+-    char stmp[D_LEN(krb5_enctype) + 1];
+-    char *p;
++    char name[64];
+ 
+-    if (nktypes < 0
+-        || len < (sizeof(" etypes {...}") + D_LEN(int))) {
+-        *s = '\0';
+-        return;
+-    }
++    if (nktypes < 0)
++        return NULL;
+ 
+-    snprintf(s, len, "%d etypes {", nktypes);
++    k5_buf_init_dynamic(&buf);
++    k5_buf_add_fmt(&buf, "%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);
++        enctype_name(ktype[i], name, sizeof(name));
++        k5_buf_add_fmt(&buf, "%s%s(%ld)", i ? ", " : "", name, (long)ktype[i]);
+     }
+-    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;
++    k5_buf_add(&buf, "}");
++    return buf.data;
+ }
+ 
+-void
+-rep_etypes2str(char *s, size_t len, krb5_kdc_rep *rep)
++char *
++rep_etypes2str(krb5_kdc_rep *rep)
+ {
+-    char stmp[sizeof("ses=") + D_LEN(krb5_enctype)];
+-
+-    if (len < (3 * D_LEN(krb5_enctype)
+-               + sizeof("etypes {rep= tkt= ses=}"))) {
+-        *s = '\0';
+-        return;
+-    }
++    struct k5buf buf;
++    char name[64];
++    krb5_enctype etype;
+ 
+-    snprintf(s, len, "etypes {rep=%ld", (long)rep->enc_part.enctype);
++    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/Make-krb5kdc-p-affect-TCP-ports.patch b/SOURCES/Make-krb5kdc-p-affect-TCP-ports.patch
deleted file mode 100644
index ac5bc30..0000000
--- a/SOURCES/Make-krb5kdc-p-affect-TCP-ports.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From 5587c1de938324faa1871e08ccfc835415acb443 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Tue, 17 Jul 2018 11:29:19 -0400
-Subject: [PATCH] Make krb5kdc -p affect TCP ports
-
-Now that the KDC listens for TCP connections by default (ticket 6731),
-the "-p" option should affect both UDP and TCP default listening
-ports.
-
-ticket: 8715 (new)
-(cherry picked from commit eb514587acc5c357bf0f554199bf0489b5515f8b)
----
- doc/admin/admin_commands/krb5kdc.rst | 12 ++++++------
- src/kdc/main.c                       | 12 ++++--------
- 2 files changed, 10 insertions(+), 14 deletions(-)
-
-diff --git a/doc/admin/admin_commands/krb5kdc.rst b/doc/admin/admin_commands/krb5kdc.rst
-index 7ec4ee4d3..bda2c015c 100644
---- a/doc/admin/admin_commands/krb5kdc.rst
-+++ b/doc/admin/admin_commands/krb5kdc.rst
-@@ -57,12 +57,12 @@ The **-P** *pid_file* option tells the KDC to write its PID into
- the KDC is still running and to allow init scripts to stop the correct
- process.
- 
--The **-p** *portnum* option specifies the default UDP port numbers
--which the KDC should listen on for Kerberos version 5 requests, as a
--comma-separated list.  This value overrides the UDP port numbers
--specified in the :ref:`kdcdefaults` section of :ref:`kdc.conf(5)`, but
--may be overridden by realm-specific values.  If no value is given from
--any source, the default port is 88.
-+The **-p** *portnum* option specifies the default UDP and TCP port
-+numbers which the KDC should listen on for Kerberos version 5
-+requests, as a comma-separated list.  This value overrides the port
-+numbers specified in the :ref:`kdcdefaults` section of
-+:ref:`kdc.conf(5)`, but may be overridden by realm-specific values.
-+If no value is given from any source, the default port is 88.
- 
- The **-w** *numworkers* option tells the KDC to fork *numworkers*
- processes to listen to the KDC ports and process requests in parallel.
-diff --git a/src/kdc/main.c b/src/kdc/main.c
-index ccac3a759..89dac23ae 100644
---- a/src/kdc/main.c
-+++ b/src/kdc/main.c
-@@ -793,19 +793,15 @@ initialize_realms(krb5_context kcontext, int argc, char **argv,
-             pid_file = optarg;
-             break;
-         case 'p':
--            if (def_udp_listen)
--                free(def_udp_listen);
-+            free(def_udp_listen);
-+            free(def_tcp_listen);
-             def_udp_listen = strdup(optarg);
--            if (!def_udp_listen) {
-+            def_tcp_listen = strdup(optarg);
-+            if (def_udp_listen == NULL || def_tcp_listen == NULL) {
-                 fprintf(stderr, _(" KDC cannot initialize. Not enough "
-                                   "memory\n"));
-                 exit(1);
-             }
--#if 0 /* not yet */
--            if (default_tcp_ports)
--                free(default_tcp_ports);
--            default_tcp_ports = strdup(optarg);
--#endif
-             break;
-         case 'T':
-             time_offset = atoi(optarg);
diff --git a/SOURCES/Mark-deprecated-enctypes-when-used.patch b/SOURCES/Mark-deprecated-enctypes-when-used.patch
new file mode 100644
index 0000000..c638cce
--- /dev/null
+++ b/SOURCES/Mark-deprecated-enctypes-when-used.patch
@@ -0,0 +1,250 @@
+From 4f56267a204764ed3d00e69cd16a0e877f055455 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/Move-zap-definition-to-k5-platform.h.patch b/SOURCES/Move-zap-definition-to-k5-platform.h.patch
deleted file mode 100644
index f181701..0000000
--- a/SOURCES/Move-zap-definition-to-k5-platform.h.patch
+++ /dev/null
@@ -1,151 +0,0 @@
-From ee941a490268bb045ec7e153bdf229adcd6d2f73 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Mon, 26 Mar 2018 10:54:29 -0400
-Subject: [PATCH] Move zap() definition to k5-platform.h
-
-Make it possible to use zap() in parts of the code which should not
-include k5-int.h by moving its definition to k5-platform.h.
-
-(cherry picked from commit df6bef6f9ea6a5f6f3956a2988cd658c78aae817)
----
- src/include/k5-int.h      | 45 -------------------------------------
- src/include/k5-platform.h | 47 ++++++++++++++++++++++++++++++++++++++-
- src/util/support/zap.c    |  4 ++--
- 3 files changed, 48 insertions(+), 48 deletions(-)
-
-diff --git a/src/include/k5-int.h b/src/include/k5-int.h
-index 1c1d9783b..69b81a7f7 100644
---- a/src/include/k5-int.h
-+++ b/src/include/k5-int.h
-@@ -639,51 +639,6 @@ krb5int_arcfour_gsscrypt(const krb5_keyblock *keyblock, krb5_keyusage usage,
- krb5_error_code
- k5_sha256(const krb5_data *in, size_t n, uint8_t out[K5_SHA256_HASHLEN]);
- 
--/*
-- * Attempt to zero memory in a way that compilers won't optimize out.
-- *
-- * This mechanism should work even for heap storage about to be freed,
-- * or automatic storage right before we return from a function.
-- *
-- * Then, even if we leak uninitialized memory someplace, or UNIX
-- * "core" files get created with world-read access, some of the most
-- * sensitive data in the process memory will already be safely wiped.
-- *
-- * We're not going so far -- yet -- as to try to protect key data that
-- * may have been written into swap space....
-- */
--#ifdef _WIN32
--# define zap(ptr, len) SecureZeroMemory(ptr, len)
--#elif defined(__STDC_LIB_EXT1__)
--/*
-- * Use memset_s() which cannot be optimized out.  Avoid memset_s(NULL, 0, 0, 0)
-- * which would cause a runtime constraint violation.
-- */
--static inline void zap(void *ptr, size_t len)
--{
--    if (len > 0)
--        memset_s(ptr, len, 0, len);
--}
--#elif defined(__GNUC__) || defined(__clang__)
--/*
-- * Use an asm statement which declares a memory clobber to force the memset to
-- * be carried out.  Avoid memset(NULL, 0, 0) which has undefined behavior.
-- */
--static inline void zap(void *ptr, size_t len)
--{
--    if (len > 0)
--        memset(ptr, 0, len);
--    __asm__ __volatile__("" : : "r" (ptr) : "memory");
--}
--#else
--/*
-- * Use a function from libkrb5support to defeat inlining unless link-time
-- * optimization is used.  The function uses a volatile pointer, which prevents
-- * current compilers from optimizing out the memset.
-- */
--# define zap(ptr, len) krb5int_zap(ptr, len)
--#endif
--
- /* Convenience function: zap and free ptr if it is non-NULL. */
- static inline void
- zapfree(void *ptr, size_t len)
-diff --git a/src/include/k5-platform.h b/src/include/k5-platform.h
-index 548c0486d..07ef6a4ca 100644
---- a/src/include/k5-platform.h
-+++ b/src/include/k5-platform.h
-@@ -40,7 +40,7 @@
-  * + [v]asprintf
-  * + strerror_r
-  * + mkstemp
-- * + zap (support function; macro is in k5-int.h)
-+ * + zap (support function and macro)
-  * + constant time memory comparison
-  * + path manipulation
-  * + _, N_, dgettext, bindtextdomain (for localization)
-@@ -1022,6 +1022,51 @@ extern int krb5int_gettimeofday(struct timeval *tp, void *ignore);
- #define gettimeofday krb5int_gettimeofday
- #endif
- 
-+/*
-+ * Attempt to zero memory in a way that compilers won't optimize out.
-+ *
-+ * This mechanism should work even for heap storage about to be freed,
-+ * or automatic storage right before we return from a function.
-+ *
-+ * Then, even if we leak uninitialized memory someplace, or UNIX
-+ * "core" files get created with world-read access, some of the most
-+ * sensitive data in the process memory will already be safely wiped.
-+ *
-+ * We're not going so far -- yet -- as to try to protect key data that
-+ * may have been written into swap space....
-+ */
-+#ifdef _WIN32
-+# define zap(ptr, len) SecureZeroMemory(ptr, len)
-+#elif defined(__STDC_LIB_EXT1__)
-+/*
-+ * Use memset_s() which cannot be optimized out.  Avoid memset_s(NULL, 0, 0, 0)
-+ * which would cause a runtime constraint violation.
-+ */
-+static inline void zap(void *ptr, size_t len)
-+{
-+    if (len > 0)
-+        memset_s(ptr, len, 0, len);
-+}
-+#elif defined(__GNUC__) || defined(__clang__)
-+/*
-+ * Use an asm statement which declares a memory clobber to force the memset to
-+ * be carried out.  Avoid memset(NULL, 0, 0) which has undefined behavior.
-+ */
-+static inline void zap(void *ptr, size_t len)
-+{
-+    if (len > 0)
-+        memset(ptr, 0, len);
-+    __asm__ __volatile__("" : : "r" (ptr) : "memory");
-+}
-+#else
-+/*
-+ * Use a function from libkrb5support to defeat inlining unless link-time
-+ * optimization is used.  The function uses a volatile pointer, which prevents
-+ * current compilers from optimizing out the memset.
-+ */
-+# define zap(ptr, len) krb5int_zap(ptr, len)
-+#endif
-+
- extern void krb5int_zap(void *ptr, size_t len);
- 
- /*
-diff --git a/src/util/support/zap.c b/src/util/support/zap.c
-index ed31630db..2f6cdd70e 100644
---- a/src/util/support/zap.c
-+++ b/src/util/support/zap.c
-@@ -25,8 +25,8 @@
-  */
- 
- /*
-- * krb5int_zap() is used by zap() (a static inline function defined in
-- * k5-int.h) on non-Windows, non-gcc compilers, in order to prevent the
-+ * krb5int_zap() is used by zap() (a macro or static inline function defined in
-+ * k5-platform.h) on non-Windows, non-gcc compilers, in order to prevent the
-  * compiler from inlining and optimizing out the memset() call.
-  */
- 
diff --git a/SOURCES/Process-profile-includedir-in-sorted-order.patch b/SOURCES/Process-profile-includedir-in-sorted-order.patch
deleted file mode 100644
index 92efffc..0000000
--- a/SOURCES/Process-profile-includedir-in-sorted-order.patch
+++ /dev/null
@@ -1,114 +0,0 @@
-From 5d868264bca1771aa16abbc8cc0aefb0e1750a73 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Wed, 6 Jun 2018 17:58:41 -0400
-Subject: [PATCH] Process profile includedir in sorted order
-
-In the profile library, use k5_dir_filenames() so that files within an
-included directory are read in a predictable order (alphanumeric
-within the C locale).
-
-ticket: 8686
-(cherry picked from commit f574eda48740ad192f51e9a382a205e2ea0e60ad)
----
- doc/admin/conf_files/krb5_conf.rst |  4 ++-
- src/util/profile/prof_parse.c      | 56 +++++-------------------------
- 2 files changed, 12 insertions(+), 48 deletions(-)
-
-diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
-index 2574e5c26..ce545492d 100644
---- a/doc/admin/conf_files/krb5_conf.rst
-+++ b/doc/admin/conf_files/krb5_conf.rst
-@@ -60,7 +60,9 @@ alphanumeric characters, dashes, or underscores.  Starting in release
- 1.15, files with names ending in ".conf" are also included, unless the
- name begins with ".".  Included profile files are syntactically
- independent of their parents, so each included file must begin with a
--section header.
-+section header.  Starting in release 1.17, files are read in
-+alphanumeric order; in previous releases, they may be read in any
-+order.
- 
- The krb5.conf file can specify that configuration should be obtained
- from a loadable module, rather than the file itself, using the
-diff --git a/src/util/profile/prof_parse.c b/src/util/profile/prof_parse.c
-index 1baceea9e..531e4a099 100644
---- a/src/util/profile/prof_parse.c
-+++ b/src/util/profile/prof_parse.c
-@@ -246,59 +246,22 @@ static int valid_name(const char *filename)
-  * Include files within dirname.  Only files with names ending in ".conf", or
-  * consisting entirely of alphanumeric characters, dashes, and underscores are
-  * included.  This restriction avoids including editor backup files, .rpmsave
-- * files, and the like.
-+ * files, and the like.  Files are processed in alphanumeric order.
-  */
- static errcode_t parse_include_dir(const char *dirname,
-                                    struct profile_node *root_section)
- {
--#ifdef _WIN32
--    char *wildcard = NULL, *pathname;
--    WIN32_FIND_DATA ffd;
--    HANDLE handle;
-     errcode_t retval = 0;
-+    char **fnames, *pathname;
-+    int i;
- 
--    if (asprintf(&wildcard, "%s\\*", dirname) < 0)
--        return ENOMEM;
--
--    handle = FindFirstFile(wildcard, &ffd);
--    if (handle == INVALID_HANDLE_VALUE) {
--        retval = PROF_FAIL_INCLUDE_DIR;
--        goto cleanup;
--    }
--
--    do {
--        if (!valid_name(ffd.cFileName))
--            continue;
--        if (asprintf(&pathname, "%s\\%s", dirname, ffd.cFileName) < 0) {
--            retval = ENOMEM;
--            break;
--        }
--        retval = parse_include_file(pathname, root_section);
--        free(pathname);
--        if (retval)
--            break;
--    } while (FindNextFile(handle, &ffd) != 0);
--
--    FindClose(handle);
--
--cleanup:
--    free(wildcard);
--    return retval;
--
--#else /* not _WIN32 */
--
--    DIR     *dir;
--    char    *pathname;
--    errcode_t retval = 0;
--    struct dirent *ent;
--
--    dir = opendir(dirname);
--    if (dir == NULL)
-+    if (k5_dir_filenames(dirname, &fnames) != 0)
-         return PROF_FAIL_INCLUDE_DIR;
--    while ((ent = readdir(dir)) != NULL) {
--        if (!valid_name(ent->d_name))
-+
-+    for (i = 0; fnames != NULL && fnames[i] != NULL; i++) {
-+        if (!valid_name(fnames[i]))
-             continue;
--        if (asprintf(&pathname, "%s/%s", dirname, ent->d_name) < 0) {
-+        if (asprintf(&pathname, "%s/%s", dirname, fnames[i]) < 0) {
-             retval = ENOMEM;
-             break;
-         }
-@@ -307,9 +270,8 @@ cleanup:
-         if (retval)
-             break;
-     }
--    closedir(dir);
-+    k5_free_filenames(fnames);
-     return retval;
--#endif /* not _WIN32 */
- }
- 
- static errcode_t parse_line(char *line, struct parse_state *state,
diff --git a/SOURCES/Properly-size-ifdef-in-k5_cccol_lock.patch b/SOURCES/Properly-size-ifdef-in-k5_cccol_lock.patch
new file mode 100644
index 0000000..001ef5a
--- /dev/null
+++ b/SOURCES/Properly-size-ifdef-in-k5_cccol_lock.patch
@@ -0,0 +1,34 @@
+From 11ebf658c737baddcd5ce91e018213f28c279737 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/Refactor-KDC-krb5_pa_data-utility-functions.patch b/SOURCES/Refactor-KDC-krb5_pa_data-utility-functions.patch
deleted file mode 100644
index 41e7cbe..0000000
--- a/SOURCES/Refactor-KDC-krb5_pa_data-utility-functions.patch
+++ /dev/null
@@ -1,393 +0,0 @@
-From 7c59b7ee063489a4259c34b725728fee7e411c46 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Thu, 21 Dec 2017 11:28:52 -0500
-Subject: [PATCH] Refactor KDC krb5_pa_data utility functions
-
-Move alloc_padata from fast_util.c to kdc_util.c and make it
-non-static so it can be used by other files.  Rename it to
-alloc_pa_data for consistency with add_pa_data_element.  Make it
-correctly handle zero length using a null contents pointer.
-
-Make add_pa_data_element claim both the container and contents memory
-from the caller, now that callers can use alloc_pa_data to simplify
-allocation and copying.  Remove the copy parameter and the unused
-context parameter, and put the list parameter first.  Adjust all
-callers accordingly, making small simplifications to memory handling
-where applicable.
-
-(cherry picked from commit 4af478c18b02e1d2444a328bb79e6976ef3d312b)
----
- src/kdc/fast_util.c   |  28 +------
- src/kdc/kdc_preauth.c |  14 ++--
- src/kdc/kdc_util.c    | 187 +++++++++++++++++++++---------------------
- src/kdc/kdc_util.h    |   8 +-
- 4 files changed, 109 insertions(+), 128 deletions(-)
-
-diff --git a/src/kdc/fast_util.c b/src/kdc/fast_util.c
-index e05107ef3..6a3fc11b9 100644
---- a/src/kdc/fast_util.c
-+++ b/src/kdc/fast_util.c
-@@ -451,36 +451,12 @@ kdc_fast_hide_client(struct kdc_request_state *state)
-     return (state->fast_options & KRB5_FAST_OPTION_HIDE_CLIENT_NAMES) != 0;
- }
- 
--/* Allocate a pa-data entry with an uninitialized buffer of size len. */
--static krb5_error_code
--alloc_padata(krb5_preauthtype pa_type, size_t len, krb5_pa_data **out)
--{
--    krb5_pa_data *pa;
--    uint8_t *buf;
--
--    *out = NULL;
--    buf = malloc(len);
--    if (buf == NULL)
--        return ENOMEM;
--    pa = malloc(sizeof(*pa));
--    if (pa == NULL) {
--        free(buf);
--        return ENOMEM;
--    }
--    pa->magic = KV5M_PA_DATA;
--    pa->pa_type = pa_type;
--    pa->length = len;
--    pa->contents = buf;
--    *out = pa;
--    return 0;
--}
--
- /* Create a pa-data entry with the specified type and contents. */
- static krb5_error_code
- make_padata(krb5_preauthtype pa_type, const void *contents, size_t len,
-             krb5_pa_data **out)
- {
--    if (alloc_padata(pa_type, len, out) != 0)
-+    if (alloc_pa_data(pa_type, len, out) != 0)
-         return ENOMEM;
-     memcpy((*out)->contents, contents, len);
-     return 0;
-@@ -720,7 +696,7 @@ kdc_fast_make_cookie(krb5_context context, struct kdc_request_state *state,
-         goto cleanup;
- 
-     /* Construct the cookie pa-data entry. */
--    ret = alloc_padata(KRB5_PADATA_FX_COOKIE, 8 + enc.ciphertext.length, &pa);
-+    ret = alloc_pa_data(KRB5_PADATA_FX_COOKIE, 8 + enc.ciphertext.length, &pa);
-     memcpy(pa->contents, "MIT1", 4);
-     store_32_be(kvno, pa->contents + 4);
-     memcpy(pa->contents + 8, enc.ciphertext.data, enc.ciphertext.length);
-diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
-index 739c5e776..edc30bd83 100644
---- a/src/kdc/kdc_preauth.c
-+++ b/src/kdc/kdc_preauth.c
-@@ -1617,18 +1617,20 @@ return_referral_enc_padata( krb5_context context,
- {
-     krb5_error_code             code;
-     krb5_tl_data                tl_data;
--    krb5_pa_data                pa_data;
-+    krb5_pa_data                *pa;
- 
-     tl_data.tl_data_type = KRB5_TL_SVR_REFERRAL_DATA;
-     code = krb5_dbe_lookup_tl_data(context, server, &tl_data);
-     if (code || tl_data.tl_data_length == 0)
-         return 0;
- 
--    pa_data.magic = KV5M_PA_DATA;
--    pa_data.pa_type = KRB5_PADATA_SVR_REFERRAL_INFO;
--    pa_data.length = tl_data.tl_data_length;
--    pa_data.contents = tl_data.tl_data_contents;
--    return add_pa_data_element(context, &pa_data, &reply->enc_padata, TRUE);
-+    code = alloc_pa_data(KRB5_PADATA_SVR_REFERRAL_INFO, tl_data.tl_data_length,
-+                         &pa);
-+    if (code)
-+        return code;
-+    memcpy(pa->contents, tl_data.tl_data_contents, tl_data.tl_data_length);
-+    /* add_pa_data_element() claims pa on success or failure. */
-+    return add_pa_data_element(&reply->enc_padata, pa);
- }
- 
- krb5_error_code
-diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
-index 754570c01..13111215d 100644
---- a/src/kdc/kdc_util.c
-+++ b/src/kdc/kdc_util.c
-@@ -1353,9 +1353,9 @@ kdc_make_s4u2self_rep(krb5_context context,
-                       krb5_enc_kdc_rep_part *reply_encpart)
- {
-     krb5_error_code             code;
--    krb5_data                   *data = NULL;
-+    krb5_data                   *der_user_id = NULL, *der_s4u_x509_user = NULL;
-     krb5_pa_s4u_x509_user       rep_s4u_user;
--    krb5_pa_data                padata;
-+    krb5_pa_data                *pa;
-     krb5_enctype                enctype;
-     krb5_keyusage               usage;
- 
-@@ -1366,7 +1366,7 @@ kdc_make_s4u2self_rep(krb5_context context,
-     rep_s4u_user.user_id.options =
-         req_s4u_user->user_id.options & KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE;
- 
--    code = encode_krb5_s4u_userid(&rep_s4u_user.user_id, &data);
-+    code = encode_krb5_s4u_userid(&rep_s4u_user.user_id, &der_user_id);
-     if (code != 0)
-         goto cleanup;
- 
-@@ -1377,29 +1377,25 @@ kdc_make_s4u2self_rep(krb5_context context,
- 
-     code = krb5_c_make_checksum(context, req_s4u_user->cksum.checksum_type,
-                                 tgs_subkey != NULL ? tgs_subkey : tgs_session,
--                                usage, data,
--                                &rep_s4u_user.cksum);
-+                                usage, der_user_id, &rep_s4u_user.cksum);
-     if (code != 0)
-         goto cleanup;
- 
--    krb5_free_data(context, data);
--    data = NULL;
--
--    code = encode_krb5_pa_s4u_x509_user(&rep_s4u_user, &data);
-+    code = encode_krb5_pa_s4u_x509_user(&rep_s4u_user, &der_s4u_x509_user);
-     if (code != 0)
-         goto cleanup;
- 
--    padata.magic = KV5M_PA_DATA;
--    padata.pa_type = KRB5_PADATA_S4U_X509_USER;
--    padata.length = data->length;
--    padata.contents = (krb5_octet *)data->data;
--
--    code = add_pa_data_element(context, &padata, &reply->padata, FALSE);
-+    /* Add a padata element, stealing memory from der_s4u_x509_user. */
-+    code = alloc_pa_data(KRB5_PADATA_S4U_X509_USER, 0, &pa);
-+    if (code != 0)
-+        goto cleanup;
-+    pa->length = der_s4u_x509_user->length;
-+    pa->contents = (uint8_t *)der_s4u_x509_user->data;
-+    der_s4u_x509_user->data = NULL;
-+    /* add_pa_data_element() claims pa on success or failure. */
-+    code = add_pa_data_element(&reply->padata, pa);
-     if (code != 0)
-         goto cleanup;
--
--    free(data);
--    data = NULL;
- 
-     if (tgs_subkey != NULL)
-         enctype = tgs_subkey->enctype;
-@@ -1413,33 +1409,27 @@ kdc_make_s4u2self_rep(krb5_context context,
-      */
-     if ((req_s4u_user->user_id.options & KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE) &&
-         enctype_requires_etype_info_2(enctype) == FALSE) {
--        padata.length = req_s4u_user->cksum.length +
--            rep_s4u_user.cksum.length;
--        padata.contents = malloc(padata.length);
--        if (padata.contents == NULL) {
--            code = ENOMEM;
-+        code = alloc_pa_data(KRB5_PADATA_S4U_X509_USER,
-+                             req_s4u_user->cksum.length +
-+                             rep_s4u_user.cksum.length, &pa);
-+        if (code != 0)
-             goto cleanup;
--        }
-+        memcpy(pa->contents,
-+               req_s4u_user->cksum.contents, req_s4u_user->cksum.length);
-+        memcpy(&pa->contents[req_s4u_user->cksum.length],
-+               rep_s4u_user.cksum.contents, rep_s4u_user.cksum.length);
- 
--        memcpy(padata.contents,
--               req_s4u_user->cksum.contents,
--               req_s4u_user->cksum.length);
--        memcpy(&padata.contents[req_s4u_user->cksum.length],
--               rep_s4u_user.cksum.contents,
--               rep_s4u_user.cksum.length);
--
--        code = add_pa_data_element(context,&padata,
--                                   &reply_encpart->enc_padata, FALSE);
--        if (code != 0) {
--            free(padata.contents);
-+        /* add_pa_data_element() claims pa on success or failure. */
-+        code = add_pa_data_element(&reply_encpart->enc_padata, pa);
-+        if (code != 0)
-             goto cleanup;
--        }
-     }
- 
- cleanup:
-     if (rep_s4u_user.cksum.contents != NULL)
-         krb5_free_checksum_contents(context, &rep_s4u_user.cksum);
--    krb5_free_data(context, data);
-+    krb5_free_data(context, der_user_id);
-+    krb5_free_data(context, der_s4u_x509_user);
- 
-     return code;
- }
-@@ -1707,46 +1697,50 @@ enctype_requires_etype_info_2(krb5_enctype enctype)
-     }
- }
- 
--/* XXX where are the generic helper routines for this? */
-+/* Allocate a pa-data entry with an uninitialized buffer of size len. */
- krb5_error_code
--add_pa_data_element(krb5_context context,
--                    krb5_pa_data *padata,
--                    krb5_pa_data ***inout_padata,
--                    krb5_boolean copy)
-+alloc_pa_data(krb5_preauthtype pa_type, size_t len, krb5_pa_data **out)
- {
--    int                         i;
--    krb5_pa_data                **p;
-+    krb5_pa_data *pa;
-+    uint8_t *buf = NULL;
- 
--    if (*inout_padata != NULL) {
--        for (i = 0; (*inout_padata)[i] != NULL; i++)
--            ;
--    } else
--        i = 0;
--
--    p = realloc(*inout_padata, (i + 2) * sizeof(krb5_pa_data *));
--    if (p == NULL)
--        return ENOMEM;
--
--    *inout_padata = p;
--
--    p[i] = (krb5_pa_data *)malloc(sizeof(krb5_pa_data));
--    if (p[i] == NULL)
--        return ENOMEM;
--    *(p[i]) = *padata;
--
--    p[i + 1] = NULL;
--
--    if (copy) {
--        p[i]->contents = (krb5_octet *)malloc(padata->length);
--        if (p[i]->contents == NULL) {
--            free(p[i]);
--            p[i] = NULL;
-+    *out = NULL;
-+    if (len > 0) {
-+        buf = malloc(len);
-+        if (buf == NULL)
-             return ENOMEM;
--        }
--
--        memcpy(p[i]->contents, padata->contents, padata->length);
-     }
-+    pa = malloc(sizeof(*pa));
-+    if (pa == NULL) {
-+        free(buf);
-+        return ENOMEM;
-+    }
-+    pa->magic = KV5M_PA_DATA;
-+    pa->pa_type = pa_type;
-+    pa->length = len;
-+    pa->contents = buf;
-+    *out = pa;
-+    return 0;
-+}
- 
-+/* Add pa to list, claiming its memory.  Free pa on failure. */
-+krb5_error_code
-+add_pa_data_element(krb5_pa_data ***list, krb5_pa_data *pa)
-+{
-+    size_t count;
-+    krb5_pa_data **newlist;
-+
-+    for (count = 0; *list != NULL && (*list)[count] != NULL; count++);
-+
-+    newlist = realloc(*list, (count + 2) * sizeof(*newlist));
-+    if (newlist == NULL) {
-+        free(pa->contents);
-+        free(pa);
-+        return ENOMEM;
-+    }
-+    newlist[count] = pa;
-+    newlist[count + 1] = NULL;
-+    *list = newlist;
-     return 0;
- }
- 
-@@ -1850,38 +1844,47 @@ kdc_handle_protected_negotiation(krb5_context context,
- {
-     krb5_error_code retval = 0;
-     krb5_checksum checksum;
--    krb5_data *out = NULL;
--    krb5_pa_data pa, *pa_in;
-+    krb5_data *der_cksum = NULL;
-+    krb5_pa_data *pa, *pa_in;
-+
-+    memset(&checksum, 0, sizeof(checksum));
-+
-     pa_in = krb5int_find_pa_data(context, request->padata,
-                                  KRB5_ENCPADATA_REQ_ENC_PA_REP);
-     if (pa_in == NULL)
-         return 0;
--    pa.magic = KV5M_PA_DATA;
--    pa.pa_type = KRB5_ENCPADATA_REQ_ENC_PA_REP;
--    memset(&checksum, 0, sizeof(checksum));
--    retval = krb5_c_make_checksum(context,0, reply_key,
--                                  KRB5_KEYUSAGE_AS_REQ, req_pkt, &checksum);
-+
-+    /* Compute and encode a checksum over the AS-REQ. */
-+    retval = krb5_c_make_checksum(context, 0, reply_key, KRB5_KEYUSAGE_AS_REQ,
-+                                  req_pkt, &checksum);
-     if (retval != 0)
-         goto cleanup;
--    retval = encode_krb5_checksum(&checksum, &out);
-+    retval = encode_krb5_checksum(&checksum, &der_cksum);
-     if (retval != 0)
-         goto cleanup;
--    pa.contents = (krb5_octet *) out->data;
--    pa.length = out->length;
--    retval = add_pa_data_element(context, &pa, out_enc_padata, FALSE);
-+
-+    /* Add a pa-data element to the list, stealing memory from der_cksum. */
-+    retval = alloc_pa_data(KRB5_ENCPADATA_REQ_ENC_PA_REP, 0, &pa);
-     if (retval)
-         goto cleanup;
--    out->data = NULL;
--    pa.magic = KV5M_PA_DATA;
--    pa.pa_type = KRB5_PADATA_FX_FAST;
--    pa.length = 0;
--    pa.contents = NULL;
--    retval = add_pa_data_element(context, &pa, out_enc_padata, FALSE);
-+    pa->length = der_cksum->length;
-+    pa->contents = (uint8_t *)der_cksum->data;
-+    der_cksum->data = NULL;
-+    /* add_pa_data_element() claims pa on success or failure. */
-+    retval = add_pa_data_element(out_enc_padata, pa);
-+    if (retval)
-+        goto cleanup;
-+
-+    /* Add a zero-length PA-FX-FAST element to the list. */
-+    retval = alloc_pa_data(KRB5_PADATA_FX_FAST, 0, &pa);
-+    if (retval)
-+        goto cleanup;
-+    /* add_pa_data_element() claims pa on success or failure. */
-+    retval = add_pa_data_element(out_enc_padata, pa);
-+
- cleanup:
--    if (checksum.contents)
--        krb5_free_checksum_contents(context, &checksum);
--    if (out != NULL)
--        krb5_free_data(context, out);
-+    krb5_free_checksum_contents(context, &checksum);
-+    krb5_free_data(context, der_cksum);
-     return retval;
- }
- 
-diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
-index c57d48f73..198eab9c4 100644
---- a/src/kdc/kdc_util.h
-+++ b/src/kdc/kdc_util.h
-@@ -202,10 +202,10 @@ void
- free_padata_context(krb5_context context, void *padata_context);
- 
- krb5_error_code
--add_pa_data_element (krb5_context context,
--                     krb5_pa_data *padata,
--                     krb5_pa_data ***out_padata,
--                     krb5_boolean copy);
-+alloc_pa_data(krb5_preauthtype pa_type, size_t len, krb5_pa_data **out);
-+
-+krb5_error_code
-+add_pa_data_element(krb5_pa_data ***list, krb5_pa_data *pa);
- 
- /* kdc_preauth_ec.c */
- krb5_error_code
diff --git a/SOURCES/Remove-incorrect-KDC-assertion.patch b/SOURCES/Remove-incorrect-KDC-assertion.patch
deleted file mode 100644
index dda0928..0000000
--- a/SOURCES/Remove-incorrect-KDC-assertion.patch
+++ /dev/null
@@ -1,59 +0,0 @@
-From 2a96564f6fd53f2e1e8424d865c02349bfe5b818 Mon Sep 17 00:00:00 2001
-From: Isaac Boukris <iboukris@gmail.com>
-Date: Sat, 15 Dec 2018 11:56:36 +0200
-Subject: [PATCH] Remove incorrect KDC assertion
-
-The assertion in return_enc_padata() is reachable because
-kdc_make_s4u2self_rep() may have previously added encrypted padata.
-It is no longer necessary because the code uses add_pa_data_element()
-instead of allocating a new list.
-
-CVE-2018-20217:
-
-In MIT krb5 1.8 or later, an authenticated user who can obtain a TGT
-using an older encryption type (DES, DES3, or RC4) can cause an
-assertion failure in the KDC by sending an S4U2Self request.
-
-[ghudson@mit.edu: rewrote commit message with CVE description]
-
-(cherry picked from commit 94e5eda5bb94d1d44733a49c3d9b6d1e42c74def)
-
-ticket: 8767
-version_fixed: 1.16.3
-
-(cherry picked from commit 56870f9456da78d77a667dfc03a6d90f948dc3a5)
----
- src/kdc/kdc_preauth.c     | 1 -
- src/tests/gssapi/t_s4u.py | 7 +++++++
- 2 files changed, 7 insertions(+), 1 deletion(-)
-
-diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
-index 811c16368..6f0cf68d9 100644
---- a/src/kdc/kdc_preauth.c
-+++ b/src/kdc/kdc_preauth.c
-@@ -1666,7 +1666,6 @@ return_enc_padata(krb5_context context, krb5_data *req_pkt,
-     krb5_error_code code = 0;
-     /* This should be initialized and only used for Win2K compat and other
-      * specific standardized uses such as FAST negotiation. */
--    assert(reply_encpart->enc_padata == NULL);
-     if (is_referral) {
-         code = return_referral_enc_padata(context, reply_encpart, server);
-         if (code)
-diff --git a/src/tests/gssapi/t_s4u.py b/src/tests/gssapi/t_s4u.py
-index fc9d9e8a4..f65000453 100755
---- a/src/tests/gssapi/t_s4u.py
-+++ b/src/tests/gssapi/t_s4u.py
-@@ -139,6 +139,13 @@ if 'auth1: user@' not in out or 'auth2: user@' not in out:
- 
- realm.stop()
- 
-+for realm in multipass_realms(create_host=False, get_creds=False):
-+    service1 = 'service/1@%s' % realm.realm
-+    realm.addprinc(service1)
-+    realm.extract_keytab(service1, realm.keytab)
-+    realm.kinit(service1, None, ['-k'])
-+    realm.run(['./t_s4u', 'p:user', '-'])
-+
- # Exercise cross-realm S4U2Self.  The query in the foreign realm will
- # fail, but we can check that the right server principal was used.
- r1, r2 = cross_realms(2, create_user=False)
diff --git a/SOURCES/Remove-nodes-option-from-make-certs-scripts.patch b/SOURCES/Remove-nodes-option-from-make-certs-scripts.patch
deleted file mode 100644
index 402f5fb..0000000
--- a/SOURCES/Remove-nodes-option-from-make-certs-scripts.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From 83da5675551dba13fee837adc26ce885a061dbc1 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Thu, 3 May 2018 14:40:45 -0400
-Subject: [PATCH] Remove "-nodes" option from make-certs scripts
-
-The openssl command does not recognize options after positional
-arguments, so in "openssl genrsa $KEYSIZE -nodes", the "-nodes" was
-ignored as a excess positional argument prior to OpenSSL 1.1.0h, and
-now causes an error.  "-nodes" is an option to the openssl req and
-pkcs12 subcommands, but genrsa creates unencrypted keys by default.
-
-[ghudson@mit.edu: edited commit message]
-
-(cherry picked from commit 928a36aae326d496c9a73f2cd41b4da45eef577c)
----
- src/tests/dejagnu/pkinit-certs/make-certs.sh | 2 +-
- src/tests/dejagnu/proxy-certs/make-certs.sh  | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/tests/dejagnu/pkinit-certs/make-certs.sh b/src/tests/dejagnu/pkinit-certs/make-certs.sh
-index 63f0c6f75..387311aed 100755
---- a/src/tests/dejagnu/pkinit-certs/make-certs.sh
-+++ b/src/tests/dejagnu/pkinit-certs/make-certs.sh
-@@ -114,7 +114,7 @@ extendedKeyUsage = $CLIENT_EKU_LIST
- EOF
- 
- # Generate a private key.
--openssl genrsa $KEYSIZE -nodes > privkey.pem
-+openssl genrsa $KEYSIZE > privkey.pem
- openssl rsa -in privkey.pem -out privkey-enc.pem -des3 -passout pass:encrypted
- 
- # Generate a "CA" certificate.
-diff --git a/src/tests/dejagnu/proxy-certs/make-certs.sh b/src/tests/dejagnu/proxy-certs/make-certs.sh
-index 1191bf05e..24ef91bde 100755
---- a/src/tests/dejagnu/proxy-certs/make-certs.sh
-+++ b/src/tests/dejagnu/proxy-certs/make-certs.sh
-@@ -79,7 +79,7 @@ extendedKeyUsage = $PROXY_EKU_LIST
- EOF
- 
- # Generate a private key.
--openssl genrsa $KEYSIZE -nodes > privkey.pem
-+openssl genrsa $KEYSIZE > privkey.pem
- 
- # Generate a "CA" certificate.
- SUBJECT=signer openssl req -config openssl.cnf -new -x509 -extensions exts_ca \
diff --git a/SOURCES/Remove-outdated-note-in-krb5kdc-man-page.patch b/SOURCES/Remove-outdated-note-in-krb5kdc-man-page.patch
deleted file mode 100644
index 6845b89..0000000
--- a/SOURCES/Remove-outdated-note-in-krb5kdc-man-page.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 65130d13c59c13b7e5e07cfe69421ce1a08c0b7f Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Tue, 17 Jul 2018 11:33:03 -0400
-Subject: [PATCH] Remove outdated note in krb5kdc man page
-
-Commit af5b77c887bfff24603715f8296c00d5eb839b0c (ticket 8348) removed
-the interface-scanning workaround for platforms without pktinfo
-support, so there is no longer an interaction between the krb5kdc -w
-option and this workaround.
-
-ticket: 8716 (new)
-tags: pullup
-target_version: 1.16-next
-
-(cherry picked from commit 728b66ab867e31c4c338c6a6309d629d39a4ec3f)
----
- doc/admin/admin_commands/krb5kdc.rst | 7 -------
- 1 file changed, 7 deletions(-)
-
-diff --git a/doc/admin/admin_commands/krb5kdc.rst b/doc/admin/admin_commands/krb5kdc.rst
-index bda2c015c..b605b563d 100644
---- a/doc/admin/admin_commands/krb5kdc.rst
-+++ b/doc/admin/admin_commands/krb5kdc.rst
-@@ -72,13 +72,6 @@ will relay SIGHUP signals to the worker subprocesses, and will
- terminate the worker subprocess if the it is itself terminated or if
- any other worker process exits.
- 
--.. note::
--
--          On operating systems which do not have *pktinfo* support,
--          using worker processes will prevent the KDC from listening
--          for UDP packets on network interfaces created after the KDC
--          starts.
--
- The **-x** *db_args* option specifies database-specific arguments.
- See :ref:`Database Options <dboptions>` in :ref:`kadmin(1)` for
- supported arguments.
diff --git a/SOURCES/Report-extended-errors-in-kinit-k-t-KDB.patch b/SOURCES/Report-extended-errors-in-kinit-k-t-KDB.patch
deleted file mode 100644
index 6859b55..0000000
--- a/SOURCES/Report-extended-errors-in-kinit-k-t-KDB.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 3b3e31316ae247e18ea22293dffbc8f604338fa7 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Sat, 17 Mar 2018 22:47:34 -0400
-Subject: [PATCH] Report extended errors in kinit -k -t KDB:
-
-In kinit, if we recreate the context using kinit_kdb_init(), also
-reset the global errctx so that we use the new context to retrieve
-extended error messages.
-
-ticket: 8652 (new)
-(cherry picked from commit d4d902d317a2acc46ee71094a33a9203b6135275)
----
- src/clients/kinit/kinit.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/clients/kinit/kinit.c b/src/clients/kinit/kinit.c
-index a518284ea..3fdae2878 100644
---- a/src/clients/kinit/kinit.c
-+++ b/src/clients/kinit/kinit.c
-@@ -718,6 +718,7 @@ k5_kinit(struct k_opts *opts, struct k5_data *k5)
- #ifndef _WIN32
-         if (strncmp(opts->keytab_name, "KDB:", 4) == 0) {
-             ret = kinit_kdb_init(&k5->ctx, k5->me->realm.data);
-+            errctx = k5->ctx;
-             if (ret) {
-                 com_err(progname, ret,
-                         _("while setting up KDB keytab for realm %s"),
diff --git a/SOURCES/Restrict-pre-authentication-fallback-cases.patch b/SOURCES/Restrict-pre-authentication-fallback-cases.patch
deleted file mode 100644
index f519557..0000000
--- a/SOURCES/Restrict-pre-authentication-fallback-cases.patch
+++ /dev/null
@@ -1,491 +0,0 @@
-From 70f41a8dafaadfb43aba4918564c22460f812dca Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Thu, 5 Apr 2018 16:23:34 -0400
-Subject: [PATCH] Restrict pre-authentication fallback cases
-
-Add a new callback disable_fallback() and call it from each clpreauth
-module when it generates a client message using credentials to
-authenticate.  (For SPAKE, this is the message responding to a
-challenge; for all other current mechanisms, it is the first and only
-client message.)  If disable_fallback() is called, do not try another
-mechanism after a KDC error.
-
-Remove k5_reset_preauth_types_tried() and its call sites, so that
-preauth mechanisms which are tried optimistically will no longer be
-retried after a failure.
-
-ticket: 8654
-(cherry picked from commit 7a24a088c16d326127dd2b29084d4ca085c70d10)
----
- src/include/krb5/clpreauth_plugin.h      | 14 ++++
- src/lib/krb5/krb/get_in_tkt.c            | 21 +++---
- src/lib/krb5/krb/init_creds_ctx.h        |  1 +
- src/lib/krb5/krb/int-proto.h             |  3 -
- src/lib/krb5/krb/preauth2.c              | 23 +++----
- src/lib/krb5/krb/preauth_ec.c            |  1 +
- src/lib/krb5/krb/preauth_encts.c         |  2 +
- src/lib/krb5/krb/preauth_otp.c           |  4 ++
- src/lib/krb5/krb/preauth_sam2.c          |  1 +
- src/plugins/preauth/pkinit/pkinit_clnt.c |  1 +
- src/plugins/preauth/spake/spake_client.c |  4 ++
- src/plugins/preauth/test/cltest.c        | 11 +++
- src/tests/t_preauth.py                   | 88 +++++++++++++++++++++---
- src/tests/t_spake.py                     |  9 +--
- 14 files changed, 134 insertions(+), 49 deletions(-)
-
-diff --git a/src/include/krb5/clpreauth_plugin.h b/src/include/krb5/clpreauth_plugin.h
-index 0106734ad..5317669b7 100644
---- a/src/include/krb5/clpreauth_plugin.h
-+++ b/src/include/krb5/clpreauth_plugin.h
-@@ -160,7 +160,21 @@ typedef struct krb5_clpreauth_callbacks_st {
-     krb5_error_code (*set_cc_config)(krb5_context context,
-                                      krb5_clpreauth_rock rock,
-                                      const char *key, const char *data);
-+
-     /* End of version 2 clpreauth callbacks (added in 1.11). */
-+
-+    /*
-+     * Prevent further fallbacks to other preauth mechanisms if the KDC replies
-+     * with an error.  (The module itself can still respond to errors with its
-+     * tryagain method, or continue after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED
-+     * errors with its process method.)  A module should invoke this callback
-+     * from the process method when it generates an authenticated request using
-+     * credentials; often this will be the first or only client message
-+     * generated by the mechanism.
-+     */
-+    void (*disable_fallback)(krb5_context context, krb5_clpreauth_rock rock);
-+
-+    /* End of version 3 clpreauth callbacks (added in 1.17). */
- } *krb5_clpreauth_callbacks;
- 
- /*
-diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
-index 1d96ff163..c026bbc6d 100644
---- a/src/lib/krb5/krb/get_in_tkt.c
-+++ b/src/lib/krb5/krb/get_in_tkt.c
-@@ -1331,9 +1331,7 @@ init_creds_step_request(krb5_context context,
-         krb5_free_pa_data(context, ctx->optimistic_padata);
-         ctx->optimistic_padata = NULL;
-         if (code) {
--            /* Make an unauthenticated request, and possibly try again using
--             * the same mechanisms as we tried optimistically. */
--            k5_reset_preauth_types_tried(ctx);
-+            /* Make an unauthenticated request. */
-             krb5_clear_error_message(context);
-             code = 0;
-         }
-@@ -1361,6 +1359,9 @@ init_creds_step_request(krb5_context context,
-     /* Don't continue after a keyboard interrupt. */
-     if (code == KRB5_LIBOS_PWDINTR)
-         goto cleanup;
-+    /* Don't continue if fallback is disabled. */
-+    if (code && ctx->fallback_disabled)
-+        goto cleanup;
-     if (code) {
-         /* See if we can try a different preauth mech before giving up. */
-         k5_save_ctx_error(context, code, &save);
-@@ -1549,16 +1550,10 @@ init_creds_step_reply(krb5_context context,
-         } else if (reply_code == KDC_ERR_PREAUTH_FAILED && retry) {
-             note_req_timestamp(context, ctx, ctx->err_reply->stime,
-                                ctx->err_reply->susec);
--            if (ctx->method_padata == NULL) {
--                /* Optimistic preauth failed on the KDC.  Allow all mechanisms
--                 * to be tried again using method data. */
--                k5_reset_preauth_types_tried(ctx);
--            } else {
--                /* Don't try again with the mechanism that failed. */
--                code = k5_preauth_note_failed(ctx, ctx->selected_preauth_type);
--                if (code)
--                    goto cleanup;
--            }
-+            /* Don't try again with the mechanism that failed. */
-+            code = k5_preauth_note_failed(ctx, ctx->selected_preauth_type);
-+            if (code)
-+                goto cleanup;
-             ctx->selected_preauth_type = KRB5_PADATA_NONE;
-             /* Accept or update method data if the KDC sent it. */
-             if (ctx->err_padata != NULL)
-diff --git a/src/lib/krb5/krb/init_creds_ctx.h b/src/lib/krb5/krb/init_creds_ctx.h
-index b19410a13..7ba61e17c 100644
---- a/src/lib/krb5/krb/init_creds_ctx.h
-+++ b/src/lib/krb5/krb/init_creds_ctx.h
-@@ -60,6 +60,7 @@ struct _krb5_init_creds_context {
-     krb5_enctype etype;
-     krb5_boolean info_pa_permitted;
-     krb5_boolean restarted;
-+    krb5_boolean fallback_disabled;
-     struct krb5_responder_context_st rctx;
-     krb5_preauthtype selected_preauth_type;
-     krb5_preauthtype allowed_preauth_type;
-diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
-index cda9010e3..d20133885 100644
---- a/src/lib/krb5/krb/int-proto.h
-+++ b/src/lib/krb5/krb/int-proto.h
-@@ -197,9 +197,6 @@ k5_init_preauth_context(krb5_context context);
- void
- k5_free_preauth_context(krb5_context context);
- 
--void
--k5_reset_preauth_types_tried(krb5_init_creds_context ctx);
--
- krb5_error_code
- k5_preauth_note_failed(krb5_init_creds_context ctx, krb5_preauthtype pa_type);
- 
-diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c
-index 451e0b7a8..1f17ec2b0 100644
---- a/src/lib/krb5/krb/preauth2.c
-+++ b/src/lib/krb5/krb/preauth2.c
-@@ -203,18 +203,6 @@ cleanup:
-     free_handles(context, list);
- }
- 
--/* Reset the memory of which preauth types we have already tried. */
--void
--k5_reset_preauth_types_tried(krb5_init_creds_context ctx)
--{
--    krb5_preauth_req_context reqctx = ctx->preauth_reqctx;
--
--    if (reqctx == NULL)
--        return;
--    free(reqctx->failed);
--    reqctx->failed = NULL;
--}
--
- /* Add pa_type to the list of types which has previously failed. */
- krb5_error_code
- k5_preauth_note_failed(krb5_init_creds_context ctx, krb5_preauthtype pa_type)
-@@ -553,8 +541,14 @@ set_cc_config(krb5_context context, krb5_clpreauth_rock rock,
-     return ret;
- }
- 
-+static void
-+disable_fallback(krb5_context context, krb5_clpreauth_rock rock)
-+{
-+    ((krb5_init_creds_context)rock)->fallback_disabled = TRUE;
-+}
-+
- static struct krb5_clpreauth_callbacks_st callbacks = {
--    2,
-+    3,
-     get_etype,
-     fast_armor,
-     get_as_key,
-@@ -564,7 +558,8 @@ static struct krb5_clpreauth_callbacks_st callbacks = {
-     responder_get_answer,
-     need_as_key,
-     get_cc_config,
--    set_cc_config
-+    set_cc_config,
-+    disable_fallback
- };
- 
- /* Tweak the request body, for now adding any enctypes which the module claims
-diff --git a/src/lib/krb5/krb/preauth_ec.c b/src/lib/krb5/krb/preauth_ec.c
-index c1aa9090f..75aab770e 100644
---- a/src/lib/krb5/krb/preauth_ec.c
-+++ b/src/lib/krb5/krb/preauth_ec.c
-@@ -138,6 +138,7 @@ ec_process(krb5_context context, krb5_clpreauth_moddata moddata,
-             encoded_ts->data = NULL;
-             *out_padata = pa;
-             pa = NULL;
-+            cb->disable_fallback(context, rock);
-         }
-         free(pa);
-         krb5_free_data(context, encoded_ts);
-diff --git a/src/lib/krb5/krb/preauth_encts.c b/src/lib/krb5/krb/preauth_encts.c
-index cec384227..45bf9da92 100644
---- a/src/lib/krb5/krb/preauth_encts.c
-+++ b/src/lib/krb5/krb/preauth_encts.c
-@@ -109,6 +109,8 @@ encts_process(krb5_context context, krb5_clpreauth_moddata moddata,
-     *out_padata = pa;
-     pa = NULL;
- 
-+    cb->disable_fallback(context, rock);
-+
- cleanup:
-     krb5_free_data(context, ts);
-     krb5_free_data(context, enc_ts);
-diff --git a/src/lib/krb5/krb/preauth_otp.c b/src/lib/krb5/krb/preauth_otp.c
-index 48fcbb5d5..13e584657 100644
---- a/src/lib/krb5/krb/preauth_otp.c
-+++ b/src/lib/krb5/krb/preauth_otp.c
-@@ -1123,6 +1123,10 @@ otp_client_process(krb5_context context, krb5_clpreauth_moddata moddata,
- 
-     /* Encode the request into the pa_data output. */
-     retval = set_pa_data(req, pa_data_out);
-+    if (retval != 0)
-+        goto error;
-+    cb->disable_fallback(context, rock);
-+
- error:
-     krb5_free_data_contents(context, &value);
-     krb5_free_data_contents(context, &pin);
-diff --git a/src/lib/krb5/krb/preauth_sam2.c b/src/lib/krb5/krb/preauth_sam2.c
-index c8a330655..4c70021a9 100644
---- a/src/lib/krb5/krb/preauth_sam2.c
-+++ b/src/lib/krb5/krb/preauth_sam2.c
-@@ -410,6 +410,7 @@ sam2_process(krb5_context context, krb5_clpreauth_moddata moddata,
-     sam_padata[1] = NULL;
- 
-     *out_padata = sam_padata;
-+    cb->disable_fallback(context, rock);
- 
-     return(0);
- }
-diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c
-index 9483d69e5..77e9e5308 100644
---- a/src/plugins/preauth/pkinit/pkinit_clnt.c
-+++ b/src/plugins/preauth/pkinit/pkinit_clnt.c
-@@ -179,6 +179,7 @@ pa_pkinit_gen_req(krb5_context context,
- 
-     *out_padata = return_pa_data;
-     return_pa_data = NULL;
-+    cb->disable_fallback(context, rock);
- 
- cleanup:
-     krb5_free_data(context, der_req);
-diff --git a/src/plugins/preauth/spake/spake_client.c b/src/plugins/preauth/spake/spake_client.c
-index 47a6ba26c..00734a13b 100644
---- a/src/plugins/preauth/spake/spake_client.c
-+++ b/src/plugins/preauth/spake/spake_client.c
-@@ -278,6 +278,10 @@ process_challenge(krb5_context context, groupstate *gstate, reqstate *st,
-         goto cleanup;
-     TRACE_SPAKE_SEND_RESPONSE(context);
-     ret = convert_to_padata(response, pa_out);
-+    if (ret)
-+        goto cleanup;
-+
-+    cb->disable_fallback(context, rock);
- 
- cleanup:
-     krb5_free_keyblock(context, k0);
-diff --git a/src/plugins/preauth/test/cltest.c b/src/plugins/preauth/test/cltest.c
-index f5f7c5aba..51b848481 100644
---- a/src/plugins/preauth/test/cltest.c
-+++ b/src/plugins/preauth/test/cltest.c
-@@ -53,6 +53,9 @@
-  * - If the "fail_optimistic", "fail_2rt", or "fail_tryagain" gic options are
-  *   set, it fails with a recognizable error string at the requested point in
-  *   processing.
-+ *
-+ * - If the "disable_fallback" gic option is set, fallback is disabled when a
-+ *   client message is generated.
-  */
- 
- #include "k5-int.h"
-@@ -66,6 +69,7 @@ struct client_state {
-     krb5_boolean fail_optimistic;
-     krb5_boolean fail_2rt;
-     krb5_boolean fail_tryagain;
-+    krb5_boolean disable_fallback;
- };
- 
- struct client_request_state {
-@@ -81,6 +85,7 @@ test_init(krb5_context context, krb5_clpreauth_moddata *moddata_out)
-     assert(st != NULL);
-     st->indicators = NULL;
-     st->fail_optimistic = st->fail_2rt = st->fail_tryagain = FALSE;
-+    st->disable_fallback = FALSE;
-     *moddata_out = (krb5_clpreauth_moddata)st;
-     return 0;
- }
-@@ -138,6 +143,8 @@ test_process(krb5_context context, krb5_clpreauth_moddata moddata,
-             return KRB5_PREAUTH_FAILED;
-         }
-         *out_pa_data = make_pa_list("optimistic", 10);
-+        if (st->disable_fallback)
-+            cb->disable_fallback(context, rock);
-         return 0;
-     } else if (reqst->second_round_trip) {
-         printf("2rt: %.*s\n", pa_data->length, pa_data->contents);
-@@ -166,6 +173,8 @@ test_process(krb5_context context, krb5_clpreauth_moddata moddata,
- 
-     indstr = (st->indicators != NULL) ? st->indicators : "";
-     *out_pa_data = make_pa_list(indstr, strlen(indstr));
-+    if (st->disable_fallback)
-+        cb->disable_fallback(context, rock);
-     return 0;
- }
- 
-@@ -212,6 +221,8 @@ test_gic_opt(krb5_context kcontext, krb5_clpreauth_moddata moddata,
-         st->fail_2rt = TRUE;
-     } else if (strcmp(attr, "fail_tryagain") == 0) {
-         st->fail_tryagain = TRUE;
-+    } else if (strcmp(attr, "disable_fallback") == 0) {
-+        st->disable_fallback = TRUE;
-     }
-     return 0;
- }
-diff --git a/src/tests/t_preauth.py b/src/tests/t_preauth.py
-index efb3ea20d..32e35b08b 100644
---- a/src/tests/t_preauth.py
-+++ b/src/tests/t_preauth.py
-@@ -37,8 +37,8 @@ expected_trace = ('Attempting optimistic preauth',
- realm.run(['./icred', '-o', '-123', realm.user_princ, password('user')],
-           expected_trace=expected_trace)
- 
--# Test optimistic preauth failing on client, followed by successful
--# preauth using the same module.
-+# Test optimistic preauth failing on client, falling back to encrypted
-+# timestamp.
- msgs = ('Attempting optimistic preauth',
-         'Processing preauth types: -123',
-         '/induced optimistic fail',
-@@ -46,15 +46,15 @@ msgs = ('Attempting optimistic preauth',
-         '/Additional pre-authentication required',
-         'Preauthenticating using KDC method data',
-         'Processing preauth types:',
--        'Preauth module test (-123) (real) returned: 0/Success',
--        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
-+        'Encrypted timestamp (for ',
-+        'module encrypted_timestamp (2) (real) returned: 0/Success',
-+        'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)',
-         'Decrypted AS reply')
- realm.run(['./icred', '-o', '-123', '-X', 'fail_optimistic', realm.user_princ,
--           password('user')], expected_msg='testval',
--          expected_trace=msgs)
-+           password('user')], expected_trace=msgs)
- 
--# Test optimistic preauth failing on KDC, followed by successful preauth
--# using the same module.
-+# Test optimistic preauth failing on KDC, falling back to encrypted
-+# timestamp.
- realm.run([kadminl, 'setstr', realm.user_princ, 'failopt', 'yes'])
- msgs = ('Attempting optimistic preauth',
-         'Processing preauth types: -123',
-@@ -63,11 +63,24 @@ msgs = ('Attempting optimistic preauth',
-         '/Preauthentication failed',
-         'Preauthenticating using KDC method data',
-         'Processing preauth types:',
--        'Preauth module test (-123) (real) returned: 0/Success',
--        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
-+        'Encrypted timestamp (for ',
-+        'module encrypted_timestamp (2) (real) returned: 0/Success',
-+        'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)',
-         'Decrypted AS reply')
- realm.run(['./icred', '-o', '-123', realm.user_princ, password('user')],
--          expected_msg='testval', expected_trace=msgs)
-+          expected_trace=msgs)
-+# Leave failopt set for the next test.
-+
-+# Test optimistic preauth failing on KDC, stopping because the test
-+# module disabled fallback.
-+msgs = ('Attempting optimistic preauth',
-+        'Processing preauth types: -123',
-+        'Preauth module test (-123) (real) returned: 0/Success',
-+        'Produced preauth for next request: -123',
-+        '/Preauthentication failed')
-+realm.run(['./icred', '-X', 'disable_fallback', '-o', '-123', realm.user_princ,
-+           password('user')], expected_code=1,
-+          expected_msg='Preauthentication failed', expected_trace=msgs)
- realm.run([kadminl, 'delstr', realm.user_princ, 'failopt'])
- 
- # Test KDC_ERR_MORE_PREAUTH_DATA_REQUIRED and secure cookies.
-@@ -107,6 +120,23 @@ msgs = ('Sending unauthenticated request',
- realm.run(['./icred', '-X', 'fail_2rt', realm.user_princ, password('user')],
-           expected_msg='2rt: secondtrip', expected_trace=msgs)
- 
-+# Test client-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED,
-+# stopping because the test module disabled fallback.
-+msgs = ('Sending unauthenticated request',
-+        '/Additional pre-authentication required',
-+        'Preauthenticating using KDC method data',
-+        'Processing preauth types:',
-+        'Preauth module test (-123) (real) returned: 0/Success',
-+        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
-+        '/More preauthentication data is required',
-+        'Continuing preauth mech -123',
-+        'Processing preauth types: -123, PA-FX-COOKIE (133)',
-+        '/induced 2rt fail')
-+realm.run(['./icred', '-X', 'fail_2rt', '-X', 'disable_fallback',
-+           realm.user_princ, password('user')], expected_code=1,
-+          expected_msg='Pre-authentication failed: induced 2rt fail',
-+          expected_trace=msgs)
-+
- # Test KDC-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED,
- # falling back to encrypted timestamp.
- realm.run([kadminl, 'setstr', realm.user_princ, 'fail2rt', 'yes'])
-@@ -130,6 +160,25 @@ msgs = ('Sending unauthenticated request',
-         'Decrypted AS reply')
- realm.run(['./icred', realm.user_princ, password('user')],
-           expected_msg='2rt: secondtrip', expected_trace=msgs)
-+# Leave fail2rt set for the next test.
-+
-+# Test KDC-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED,
-+# stopping because the test module disabled fallback.
-+msgs = ('Sending unauthenticated request',
-+        '/Additional pre-authentication required',
-+        'Preauthenticating using KDC method data',
-+        'Processing preauth types:',
-+        'Preauth module test (-123) (real) returned: 0/Success',
-+        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
-+        '/More preauthentication data is required',
-+        'Continuing preauth mech -123',
-+        'Processing preauth types: -123, PA-FX-COOKIE (133)',
-+        'Preauth module test (-123) (real) returned: 0/Success',
-+        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
-+        '/Preauthentication failed')
-+realm.run(['./icred', '-X', 'disable_fallback',
-+           realm.user_princ, password('user')], expected_code=1,
-+          expected_msg='Preauthentication failed', expected_trace=msgs)
- realm.run([kadminl, 'delstr', realm.user_princ, 'fail2rt'])
- 
- # Test tryagain flow by inducing a KDC_ERR_ENCTYPE_NOSUPP error on the KDC.
-@@ -170,6 +219,23 @@ msgs = ('Sending unauthenticated request',
- realm.run(['./icred', '-X', 'fail_tryagain', realm.user_princ,
-            password('user')], expected_trace=msgs)
- 
-+# Test a client-side tryagain failure, stopping because the test
-+# module disabled fallback.
-+msgs = ('Sending unauthenticated request',
-+        '/Additional pre-authentication required',
-+        'Preauthenticating using KDC method data',
-+        'Processing preauth types:',
-+        'Preauth module test (-123) (real) returned: 0/Success',
-+        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
-+        '/KDC has no support for encryption type',
-+        'Recovering from KDC error 14 using preauth mech -123',
-+        'Preauth tryagain input types (-123): -123, PA-FX-COOKIE (133)',
-+        '/induced tryagain fail')
-+realm.run(['./icred', '-X', 'fail_tryagain', '-X', 'disable_fallback',
-+           realm.user_princ, password('user')], expected_code=1,
-+          expected_msg='KDC has no support for encryption type',
-+          expected_trace=msgs)
-+
- # Test that multiple stepwise initial creds operations can be
- # performed with the same krb5_context, with proper tracking of
- # clpreauth module request handles.
-diff --git a/src/tests/t_spake.py b/src/tests/t_spake.py
-index a81a238b4..5b47e62d3 100644
---- a/src/tests/t_spake.py
-+++ b/src/tests/t_spake.py
-@@ -31,9 +31,7 @@ for gnum, gname in groups:
-                 'Decrypted AS reply')
-         realm.kinit('user', 'pw', expected_trace=msgs)
- 
--        # Test an unsuccessful authentication.  (The client will try
--        # again with encrypted timestamp, which isn't really desired,
--        # but check for that as long as it is expected.)
-+        # Test an unsuccessful authentication.
-         msgs = ('/Additional pre-authentication required',
-                 'Selected etype info:',
-                 'Sending SPAKE support message',
-@@ -42,9 +40,6 @@ for gnum, gname in groups:
-                 'Continuing preauth mech PA-SPAKE (151)',
-                 'SPAKE challenge received with group ' + str(gnum),
-                 'Sending SPAKE response',
--                '/Preauthentication failed',
--                'Encrypted timestamp ',
--                'for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)',
-                 '/Preauthentication failed')
-         realm.kinit('user', 'wrongpw', expected_code=1, expected_trace=msgs)
- 
-@@ -114,8 +109,6 @@ msgs = ('Attempting optimistic preauth',
-         'for next request: PA-SPAKE (151)',
-         '/Preauthentication failed',
-         'Selected etype info:',
--        'SPAKE challenge with group 1 rejected',
--        'spake (151) (real) returned: -1765328360/Preauthentication failed',
-         'Encrypted timestamp ',
-         'for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)',
-         'AS key determined by preauth:',
diff --git a/SOURCES/Simplify-kdc_preauth.c-systems-table.patch b/SOURCES/Simplify-kdc_preauth.c-systems-table.patch
deleted file mode 100644
index 08853d4..0000000
--- a/SOURCES/Simplify-kdc_preauth.c-systems-table.patch
+++ /dev/null
@@ -1,738 +0,0 @@
-From 65f078dfc68f5680e87e686a59970291b64ebd95 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Sun, 11 Feb 2018 15:23:35 -0500
-Subject: [PATCH] Simplify kdc_preauth.c systems table
-
-Get rid of static_preauth_systems, and replace it with explicit calls
-to helper functions in get_preauth_hint_list() and return_padata().
-Stop preallocating pa-data lists, instead reallocating on each
-addition using add_pa_data_element().  Also simplify
-maybe_add_etype_info2() using add_pa_data_element().
-
-The KRB5_PADATA_PAC_REQUEST table entry did nothing, and was probably
-originally added back when the KDC would error out on unrecognized
-padata types.  The KRB5_PADATA_SERVER_REFERRAL entry has been disabled
-since it was first added.
-
-(cherry picked from commit fea1a488924faa3938ef723feaa1ff12d22a91ff)
----
- src/kdc/kdc_preauth.c | 526 +++++++++++++++---------------------------
- 1 file changed, 184 insertions(+), 342 deletions(-)
-
-diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
-index edc30bd83..6f34dc289 100644
---- a/src/kdc/kdc_preauth.c
-+++ b/src/kdc/kdc_preauth.c
-@@ -101,108 +101,14 @@ typedef struct preauth_system_st {
-     krb5_kdcpreauth_loop_fn loop;
- } preauth_system;
- 
-+static preauth_system *preauth_systems;
-+static size_t n_preauth_systems;
-+
- static krb5_error_code
- make_etype_info(krb5_context context, krb5_preauthtype pa_type,
-                 krb5_principal client, krb5_key_data *client_key,
-                 krb5_enctype enctype, krb5_pa_data **pa_out);
- 
--static void
--get_etype_info(krb5_context context, krb5_kdc_req *request,
--               krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
--               krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type,
--               krb5_kdcpreauth_edata_respond_fn respond, void *arg);
--
--static krb5_error_code
--return_etype_info(krb5_context, krb5_pa_data *padata,
--                  krb5_data *req_pkt, krb5_kdc_req *request,
--                  krb5_kdc_rep *reply, krb5_keyblock *encrypting_key,
--                  krb5_pa_data **send_pa, krb5_kdcpreauth_callbacks cb,
--                  krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata,
--                  krb5_kdcpreauth_modreq modreq);
--
--static krb5_error_code
--return_pw_salt(krb5_context, krb5_pa_data *padata,
--               krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply,
--               krb5_keyblock *encrypting_key, krb5_pa_data **send_pa,
--               krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
--               krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq);
--
--
--
--static preauth_system static_preauth_systems[] = {
--    {
--        "FAST",
--        KRB5_PADATA_FX_FAST,
--        PA_HARDWARE,
--        NULL,
--        NULL,
--        NULL,
--        NULL,
--        NULL,
--        0
--    },
--    {
--        "etype-info",
--        KRB5_PADATA_ETYPE_INFO,
--        PA_HARDWARE,
--        NULL,
--        NULL,
--        NULL,
--        get_etype_info,
--        0,
--        return_etype_info
--    },
--    {
--        "etype-info2",
--        KRB5_PADATA_ETYPE_INFO2,
--        PA_HARDWARE,
--        NULL,
--        NULL,
--        NULL,
--        get_etype_info,
--        0,
--        return_etype_info
--    },
--    {
--        "pw-salt",
--        KRB5_PADATA_PW_SALT,
--        PA_PSEUDO,              /* Don't include this in the error list */
--        NULL,
--        NULL,
--        NULL,
--        0,
--        0,
--        return_pw_salt
--    },
--    {
--        "pac-request",
--        KRB5_PADATA_PAC_REQUEST,
--        PA_PSEUDO,
--        NULL,
--        NULL,
--        NULL,
--        NULL,
--        NULL,
--        NULL
--    },
--#if 0
--    {
--        "server-referral",
--        KRB5_PADATA_SERVER_REFERRAL,
--        PA_PSEUDO,
--        0,
--        0,
--        return_server_referral
--    },
--#endif
--};
--
--#define NUM_STATIC_PREAUTH_SYSTEMS (sizeof(static_preauth_systems) /    \
--                                    sizeof(*static_preauth_systems))
--
--static preauth_system *preauth_systems;
--static size_t n_preauth_systems;
--
- /* Get all available kdcpreauth vtables and a count of preauth types they
-  * support.  Return an empty list on failure. */
- static void
-@@ -284,7 +190,6 @@ load_preauth_plugins(struct server_handle *handle, krb5_context context,
-     get_plugin_vtables(context, &vtables, &n_tables, &n_systems);
- 
-     /* Allocate the list of static and plugin preauth systems. */
--    n_systems += NUM_STATIC_PREAUTH_SYSTEMS;
-     preauth_systems = calloc(n_systems + 1, sizeof(preauth_system));
-     if (preauth_systems == NULL)
-         goto cleanup;
-@@ -292,13 +197,8 @@ load_preauth_plugins(struct server_handle *handle, krb5_context context,
-     if (get_realm_names(handle, &realm_names))
-         goto cleanup;
- 
--    /* Add the static system to the list first.  No static systems require
--     * initialization, so just make a direct copy. */
--    memcpy(preauth_systems, static_preauth_systems,
--           sizeof(static_preauth_systems));
--
-     /* Add the dynamically-loaded mechanisms to the list. */
--    n_systems = NUM_STATIC_PREAUTH_SYSTEMS;
-+    n_systems = 0;
-     for (i = 0; i < n_tables; i++) {
-         /* Try to initialize this module. */
-         vt = &vtables[i];
-@@ -622,7 +522,9 @@ find_pa_system(int type, preauth_system **preauth)
- {
-     preauth_system *ap;
- 
--    ap = preauth_systems ? preauth_systems : static_preauth_systems;
-+    if (preauth_systems == NULL)
-+        return KRB5_PREAUTH_BAD_TYPE;
-+    ap = preauth_systems;
-     while ((ap->type != -1) && (ap->type != type))
-         ap++;
-     if (ap->type == -1)
-@@ -776,6 +678,98 @@ const char *missing_required_preauth(krb5_db_entry *client,
-     return 0;
- }
- 
-+/* Return true if request's enctypes indicate support for etype-info2. */
-+static krb5_boolean
-+requires_info2(const krb5_kdc_req *request)
-+{
-+    int i;
-+
-+    for (i = 0; i < request->nktypes; i++) {
-+        if (enctype_requires_etype_info_2(request->ktype[i]))
-+            return TRUE;
-+    }
-+    return FALSE;
-+}
-+
-+/* Add PA-ETYPE-INFO2 and possibly PA-ETYPE-INFO entries to pa_list as
-+ * appropriate for the request and client principal. */
-+static krb5_error_code
-+add_etype_info(krb5_context context, krb5_kdcpreauth_rock rock,
-+               krb5_pa_data ***pa_list)
-+{
-+    krb5_error_code ret;
-+    krb5_pa_data *pa;
-+
-+    if (rock->client_key == NULL)
-+        return 0;
-+
-+    if (!requires_info2(rock->request)) {
-+        /* Include PA-ETYPE-INFO only for old clients. */
-+        ret = make_etype_info(context, KRB5_PADATA_ETYPE_INFO,
-+                              rock->client->princ, rock->client_key,
-+                              rock->client_keyblock->enctype, &pa);
-+        if (ret)
-+            return ret;
-+        /* add_pa_data_element() claims pa on success or failure. */
-+        ret = add_pa_data_element(pa_list, pa);
-+        if (ret)
-+            return ret;
-+    }
-+
-+    /* Always include PA-ETYPE-INFO2. */
-+    ret = make_etype_info(context, KRB5_PADATA_ETYPE_INFO2,
-+                          rock->client->princ, rock->client_key,
-+                          rock->client_keyblock->enctype, &pa);
-+    if (ret)
-+        return ret;
-+    /* add_pa_data_element() claims pa on success or failure. */
-+    return add_pa_data_element(pa_list, pa);
-+}
-+
-+/* Add PW-SALT or AFS3-SALT entries to pa_list as appropriate for the request
-+ * and client principal. */
-+static krb5_error_code
-+add_pw_salt(krb5_context context, krb5_kdcpreauth_rock rock,
-+            krb5_pa_data ***pa_list)
-+{
-+    krb5_error_code ret;
-+    krb5_pa_data *pa;
-+    krb5_data *salt = NULL;
-+    krb5_int16 salttype;
-+
-+    /* Only include this pa-data for old clients. */
-+    if (rock->client_key == NULL || requires_info2(rock->request))
-+        return 0;
-+
-+    ret = krb5_dbe_compute_salt(context, rock->client_key,
-+                                rock->request->client, &salttype, &salt);
-+    if (ret)
-+        return 0;
-+
-+    if (salttype == KRB5_KDB_SALTTYPE_AFS3) {
-+        ret = alloc_pa_data(KRB5_PADATA_AFS3_SALT, salt->length + 1, &pa);
-+        if (ret)
-+            goto cleanup;
-+        memcpy(pa->contents, salt->data, salt->length);
-+        pa->contents[salt->length] = '\0';
-+    } else {
-+        /* Steal memory from salt to make the pa-data entry. */
-+        ret = alloc_pa_data(KRB5_PADATA_PW_SALT, 0, &pa);
-+        if (ret)
-+            goto cleanup;
-+        pa->length = salt->length;
-+        pa->contents = (uint8_t *)salt->data;
-+        salt->data = NULL;
-+    }
-+
-+    /* add_pa_data_element() claims pa on success or failure. */
-+    ret = add_pa_data_element(pa_list, pa);
-+
-+cleanup:
-+    krb5_free_data(context, salt);
-+    return ret;
-+}
-+
- struct hint_state {
-     kdc_hint_respond_fn respond;
-     void *arg;
-@@ -787,7 +781,7 @@ struct hint_state {
- 
-     int hw_only;
-     preauth_system *ap;
--    krb5_pa_data **pa_data, **pa_cur;
-+    krb5_pa_data **pa_data;
-     krb5_preauthtype pa_type;
- };
- 
-@@ -799,7 +793,7 @@ hint_list_finish(struct hint_state *state, krb5_error_code code)
-     kdc_realm_t *kdc_active_realm = state->realm;
- 
-     if (!code) {
--        if (state->pa_data[0] == 0) {
-+        if (state->pa_data == NULL) {
-             krb5_klog_syslog(LOG_INFO,
-                              _("%spreauth required but hint list is empty"),
-                              state->hw_only ? "hw" : "");
-@@ -820,20 +814,27 @@ hint_list_next(struct hint_state *arg);
- static void
- finish_get_edata(void *arg, krb5_error_code code, krb5_pa_data *pa)
- {
-+    krb5_error_code ret;
-     struct hint_state *state = arg;
- 
-     if (code == 0) {
-         if (pa == NULL) {
--            /* Include an empty value of the current type. */
--            pa = calloc(1, sizeof(*pa));
--            pa->magic = KV5M_PA_DATA;
--            pa->pa_type = state->pa_type;
-+            ret = alloc_pa_data(state->pa_type, 0, &pa);
-+            if (ret)
-+                goto error;
-         }
--        *state->pa_cur++ = pa;
-+        /* add_pa_data_element() claims pa on success or failure. */
-+        ret = add_pa_data_element(&state->pa_data, pa);
-+        if (ret)
-+            goto error;
-     }
- 
-     state->ap++;
-     hint_list_next(state);
-+    return;
-+
-+error:
-+    hint_list_finish(state, ret);
- }
- 
- static void
-@@ -870,16 +871,16 @@ get_preauth_hint_list(krb5_kdc_req *request, krb5_kdcpreauth_rock rock,
-                       krb5_pa_data ***e_data_out, kdc_hint_respond_fn respond,
-                       void *arg)
- {
-+    kdc_realm_t *kdc_active_realm = rock->rstate->realm_data;
-     struct hint_state *state;
-+    krb5_pa_data *pa;
- 
-     *e_data_out = NULL;
- 
-     /* Allocate our state. */
-     state = calloc(1, sizeof(*state));
--    if (state == NULL) {
--        (*respond)(arg);
--        return;
--    }
-+    if (state == NULL)
-+        goto error;
-     state->hw_only = isflagset(rock->client->attributes,
-                                KRB5_KDB_REQUIRES_HW_AUTH);
-     state->respond = respond;
-@@ -888,17 +889,27 @@ get_preauth_hint_list(krb5_kdc_req *request, krb5_kdcpreauth_rock rock,
-     state->rock = rock;
-     state->realm = rock->rstate->realm_data;
-     state->e_data_out = e_data_out;
--
--    state->pa_data = calloc(n_preauth_systems + 1, sizeof(krb5_pa_data *));
--    if (!state->pa_data) {
--        free(state);
--        (*respond)(arg);
--        return;
--    }
--
--    state->pa_cur = state->pa_data;
-+    state->pa_data = NULL;
-     state->ap = preauth_systems;
-+
-+    /* Add an empty PA-FX-FAST element to advertise FAST support. */
-+    if (alloc_pa_data(KRB5_PADATA_FX_FAST, 0, &pa) != 0)
-+        goto error;
-+    /* add_pa_data_element() claims pa on success or failure. */
-+    if (add_pa_data_element(&state->pa_data, pa) != 0)
-+        goto error;
-+
-+    if (add_etype_info(kdc_context, rock, &state->pa_data) != 0)
-+        goto error;
-+
-     hint_list_next(state);
-+    return;
-+
-+error:
-+    if (state != NULL)
-+        krb5_free_pa_data(kdc_context, state->pa_data);
-+    free(state);
-+    (*respond)(arg);
- }
- 
- /*
-@@ -1029,10 +1040,10 @@ filter_preauth_error(krb5_error_code code)
- static krb5_error_code
- maybe_add_etype_info2(struct padata_state *state, krb5_error_code code)
- {
-+    krb5_error_code ret;
-     krb5_context context = state->context;
-     krb5_kdcpreauth_rock rock = state->rock;
--    krb5_pa_data **list = state->pa_e_data;
--    size_t count;
-+    krb5_pa_data *pa;
- 
-     /* Only add key information when requesting another preauth round trip. */
-     if (code != KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED)
-@@ -1048,18 +1059,14 @@ maybe_add_etype_info2(struct padata_state *state, krb5_error_code code)
-                              KRB5_PADATA_FX_COOKIE) != NULL)
-         return 0;
- 
--    /* Reallocate state->pa_e_data to make room for the etype-info2 element. */
--    for (count = 0; list != NULL && list[count] != NULL; count++);
--    list = realloc(list, (count + 2) * sizeof(*list));
--    if (list == NULL)
--        return ENOMEM;
--    list[count] = list[count + 1] = NULL;
--    state->pa_e_data = list;
-+    ret = make_etype_info(context, KRB5_PADATA_ETYPE_INFO2,
-+                          rock->client->princ, rock->client_key,
-+                          rock->client_keyblock->enctype, &pa);
-+    if (ret)
-+        return ret;
- 
--    /* Generate an etype-info2 element in the new slot. */
--    return make_etype_info(context, KRB5_PADATA_ETYPE_INFO2,
--                           rock->client->princ, rock->client_key,
--                           rock->client_keyblock->enctype, &list[count]);
-+    /* add_pa_data_element() claims pa on success or failure. */
-+    return add_pa_data_element(&state->pa_e_data, pa);
- }
- 
- /* Release state and respond to the AS-REQ processing code with the result of
-@@ -1279,17 +1286,20 @@ return_padata(krb5_context context, krb5_kdcpreauth_rock rock,
- {
-     krb5_error_code             retval;
-     krb5_pa_data **             padata;
--    krb5_pa_data **             send_pa_list;
--    krb5_pa_data **             send_pa;
-+    krb5_pa_data **             send_pa_list = NULL;
-+    krb5_pa_data *              send_pa;
-     krb5_pa_data *              pa = 0;
-     krb5_pa_data null_item;
-     preauth_system *            ap;
--    int *                       pa_order;
-+    int *                       pa_order = NULL;
-     int *                       pa_type;
-     int                         size = 0;
-     krb5_kdcpreauth_modreq      *modreq_ptr;
-     krb5_boolean                key_modified;
-     krb5_keyblock               original_key;
-+
-+    memset(&original_key, 0, sizeof(original_key));
-+
-     if ((!*padata_context) &&
-         (make_padata_context(context, padata_context) != 0)) {
-         return KRB5KRB_ERR_GENERIC;
-@@ -1300,26 +1310,18 @@ return_padata(krb5_context context, krb5_kdcpreauth_rock rock,
-             size++;
-     }
- 
--    if ((send_pa_list = malloc((size+1) * sizeof(krb5_pa_data *))) == NULL)
--        return ENOMEM;
--    if ((pa_order = malloc((size+1) * sizeof(int))) == NULL) {
--        free(send_pa_list);
--        return ENOMEM;
--    }
-+    pa_order = k5calloc(size + 1, sizeof(int), &retval);
-+    if (pa_order == NULL)
-+        goto cleanup;
-     sort_pa_order(context, request, pa_order);
- 
-     retval = krb5_copy_keyblock_contents(context, encrypting_key,
-                                          &original_key);
--    if (retval) {
--        free(send_pa_list);
--        free(pa_order);
--        return retval;
--    }
-+    if (retval)
-+        goto cleanup;
-     key_modified = FALSE;
-     null_item.contents = NULL;
-     null_item.length = 0;
--    send_pa = send_pa_list;
--    *send_pa = 0;
- 
-     for (pa_type = pa_order; *pa_type != -1; pa_type++) {
-         ap = &preauth_systems[*pa_type];
-@@ -1349,20 +1351,30 @@ return_padata(krb5_context context, krb5_kdcpreauth_rock rock,
-                 }
-             }
-         }
-+        send_pa = NULL;
-         retval = ap->return_padata(context, pa, req_pkt, request, reply,
--                                   encrypting_key, send_pa, &callbacks, rock,
-+                                   encrypting_key, &send_pa, &callbacks, rock,
-                                    ap->moddata, *modreq_ptr);
-         if (retval)
-             goto cleanup;
- 
--        if (*send_pa)
--            send_pa++;
--        *send_pa = 0;
-+        if (send_pa != NULL) {
-+            /* add_pa_data_element() claims send_pa on success or failure. */
-+            retval = add_pa_data_element(&send_pa_list, send_pa);
-+            if (retval)
-+                goto cleanup;
-+        }
-     }
- 
--    retval = 0;
-+    /* Add etype-info and pw-salt pa-data as needed. */
-+    retval = add_etype_info(context, rock, &send_pa_list);
-+    if (retval)
-+        goto cleanup;
-+    retval = add_pw_salt(context, rock, &send_pa_list);
-+    if (retval)
-+        goto cleanup;
- 
--    if (send_pa_list[0]) {
-+    if (send_pa_list != NULL) {
-         reply->padata = send_pa_list;
-         send_pa_list = 0;
-     }
-@@ -1370,8 +1382,7 @@ return_padata(krb5_context context, krb5_kdcpreauth_rock rock,
- cleanup:
-     krb5_free_keyblock_contents(context, &original_key);
-     free(pa_order);
--    if (send_pa_list)
--        krb5_free_pa_data(context, send_pa_list);
-+    krb5_free_pa_data(context, send_pa_list);
- 
-     return (retval);
- }
-@@ -1438,9 +1449,8 @@ make_etype_info(krb5_context context, krb5_preauthtype pa_type,
-                 krb5_enctype enctype, krb5_pa_data **pa_out)
- {
-     krb5_error_code retval;
--    krb5_pa_data *pa = NULL;
-     krb5_etype_info_entry **entry = NULL;
--    krb5_data *scratch = NULL;
-+    krb5_data *der_etype_info = NULL;
-     int etype_info2 = (pa_type == KRB5_PADATA_ETYPE_INFO2);
- 
-     *pa_out = NULL;
-@@ -1454,125 +1464,23 @@ make_etype_info(krb5_context context, krb5_preauthtype pa_type,
-         goto cleanup;
- 
-     if (etype_info2)
--        retval = encode_krb5_etype_info2(entry, &scratch);
-+        retval = encode_krb5_etype_info2(entry, &der_etype_info);
-     else
--        retval = encode_krb5_etype_info(entry, &scratch);
-+        retval = encode_krb5_etype_info(entry, &der_etype_info);
-     if (retval)
-         goto cleanup;
--    pa = k5alloc(sizeof(*pa), &retval);
--    if (pa == NULL)
-+
-+    /* Steal the data from der_etype_info to create a pa-data element. */
-+    retval = alloc_pa_data(pa_type, 0, pa_out);
-+    if (retval)
-         goto cleanup;
--    pa->magic = KV5M_PA_DATA;
--    pa->pa_type = pa_type;
--    pa->contents = (unsigned char *)scratch->data;
--    pa->length = scratch->length;
--    scratch->data = NULL;
--    *pa_out = pa;
-+    (*pa_out)->contents = (uint8_t *)der_etype_info->data;
-+    (*pa_out)->length = der_etype_info->length;
-+    der_etype_info->data = NULL;
- 
- cleanup:
-     krb5_free_etype_info(context, entry);
--    krb5_free_data(context, scratch);
--    return retval;
--}
--
--/* Return true if request's enctypes indicate support for etype-info2. */
--static krb5_boolean
--requires_info2(const krb5_kdc_req *request)
--{
--    int i;
--
--    for (i = 0; i < request->nktypes; i++) {
--        if (enctype_requires_etype_info_2(request->ktype[i]))
--            return TRUE;
--    }
--    return FALSE;
--}
--
--/* Generate hint list padata for PA-ETYPE-INFO or PA-ETYPE-INFO2. */
--static void
--get_etype_info(krb5_context context, krb5_kdc_req *request,
--               krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
--               krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type,
--               krb5_kdcpreauth_edata_respond_fn respond, void *arg)
--{
--    krb5_error_code ret;
--    krb5_pa_data *pa = NULL;
--
--    if (rock->client_key == NULL) {
--        ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
--    } else if (pa_type == KRB5_PADATA_ETYPE_INFO && requires_info2(request)) {
--        ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
--    } else {
--        ret = make_etype_info(context, pa_type, rock->client->princ,
--                              rock->client_key, rock->client_keyblock->enctype,
--                              &pa);
--    }
--    (*respond)(arg, ret, pa);
--}
--
--/* Generate AS-REP padata for PA-ETYPE-INFO or PA-ETYPE-INFO2. */
--static krb5_error_code
--return_etype_info(krb5_context context, krb5_pa_data *padata,
--                  krb5_data *req_pkt, krb5_kdc_req *request,
--                  krb5_kdc_rep *reply, krb5_keyblock *encrypting_key,
--                  krb5_pa_data **send_pa, krb5_kdcpreauth_callbacks cb,
--                  krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata,
--                  krb5_kdcpreauth_modreq modreq)
--{
--    *send_pa = NULL;
--    if (rock->client_key == NULL)
--        return 0;
--    if (padata->pa_type == KRB5_PADATA_ETYPE_INFO && requires_info2(request))
--        return 0;
--    return make_etype_info(context, padata->pa_type, rock->client->princ,
--                           rock->client_key, encrypting_key->enctype, send_pa);
--}
--
--static krb5_error_code
--return_pw_salt(krb5_context context, krb5_pa_data *in_padata,
--               krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply,
--               krb5_keyblock *encrypting_key, krb5_pa_data **send_pa,
--               krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
--               krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq)
--{
--    krb5_error_code     retval;
--    krb5_pa_data *      padata;
--    krb5_data *         salt = NULL;
--    krb5_int16          salttype;
--    krb5_key_data *     client_key = rock->client_key;
--
--    if (client_key == NULL || requires_info2(request))
--        return 0;
--
--    retval = krb5_dbe_compute_salt(context, client_key, request->client,
--                                   &salttype, &salt);
--    if (retval)
--        return 0;
--
--    padata = k5alloc(sizeof(*padata), &retval);
--    if (padata == NULL)
--        goto cleanup;
--    padata->magic = KV5M_PA_DATA;
--
--    if (salttype == KRB5_KDB_SALTTYPE_AFS3) {
--        padata->contents = k5memdup0(salt->data, salt->length, &retval);
--        if (padata->contents == NULL)
--            goto cleanup;
--        padata->pa_type = KRB5_PADATA_AFS3_SALT;
--        padata->length = salt->length + 1;
--    } else {
--        padata->pa_type = KRB5_PADATA_PW_SALT;
--        padata->length = salt->length;
--        padata->contents = (krb5_octet *)salt->data;
--        salt->data = NULL;
--    }
--
--    *send_pa = padata;
--    padata = NULL;
--
--cleanup:
--    free(padata);
--    krb5_free_data(context, salt);
-+    krb5_free_data(context, der_etype_info);
-     return retval;
- }
- 
-@@ -1656,69 +1564,3 @@ return_enc_padata(krb5_context context, krb5_data *req_pkt,
- cleanup:
-     return code;
- }
--
--
--#if 0
--static krb5_error_code return_server_referral(krb5_context context,
--                                              krb5_pa_data * padata,
--                                              krb5_db_entry *client,
--                                              krb5_db_entry *server,
--                                              krb5_kdc_req *request,
--                                              krb5_kdc_rep *reply,
--                                              krb5_key_data *client_key,
--                                              krb5_keyblock *encrypting_key,
--                                              krb5_pa_data **send_pa)
--{
--    krb5_error_code             code;
--    krb5_tl_data                tl_data;
--    krb5_pa_data                *pa_data;
--    krb5_enc_data               enc_data;
--    krb5_data                   plain;
--    krb5_data                   *enc_pa_data;
--
--    *send_pa = NULL;
--
--    tl_data.tl_data_type = KRB5_TL_SERVER_REFERRAL;
--
--    code = krb5_dbe_lookup_tl_data(context, server, &tl_data);
--    if (code || tl_data.tl_data_length == 0)
--        return 0; /* no server referrals to return */
--
--    plain.length = tl_data.tl_data_length;
--    plain.data = tl_data.tl_data_contents;
--
--    /* Encrypt ServerReferralData */
--    code = krb5_encrypt_helper(context, encrypting_key,
--                               KRB5_KEYUSAGE_PA_SERVER_REFERRAL_DATA,
--                               &plain, &enc_data);
--    if (code)
--        return code;
--
--    /* Encode ServerReferralData into PA-SERVER-REFERRAL-DATA */
--    code = encode_krb5_enc_data(&enc_data, &enc_pa_data);
--    if (code) {
--        krb5_free_data_contents(context, &enc_data.ciphertext);
--        return code;
--    }
--
--    krb5_free_data_contents(context, &enc_data.ciphertext);
--
--    /* Return PA-SERVER-REFERRAL-DATA */
--    pa_data = (krb5_pa_data *)malloc(sizeof(*pa_data));
--    if (pa_data == NULL) {
--        krb5_free_data(context, enc_pa_data);
--        return ENOMEM;
--    }
--
--    pa_data->magic = KV5M_PA_DATA;
--    pa_data->pa_type = KRB5_PADATA_SVR_REFERRAL_INFO;
--    pa_data->length = enc_pa_data->length;
--    pa_data->contents = enc_pa_data->data;
--
--    free(enc_pa_data); /* don't free contents */
--
--    *send_pa = pa_data;
--
--    return 0;
--}
--#endif
diff --git a/SOURCES/Use-SHA-256-instead-of-MD5-for-audit-ticket-IDs.patch b/SOURCES/Use-SHA-256-instead-of-MD5-for-audit-ticket-IDs.patch
deleted file mode 100644
index 26df25a..0000000
--- a/SOURCES/Use-SHA-256-instead-of-MD5-for-audit-ticket-IDs.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From a9bc03fe03ef4b00bcdad13c99bb4c376a8b9964 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Tue, 10 Jul 2018 16:17:15 -0400
-Subject: [PATCH] Use SHA-256 instead of MD5 for audit ticket IDs
-
-ticket: 8711 (new)
-(cherry picked from commit c1e1bfa26bd2f045e88e6013c500fca9428c98f3)
----
- src/kdc/kdc_audit.c | 21 ++++++++++-----------
- 1 file changed, 10 insertions(+), 11 deletions(-)
-
-diff --git a/src/kdc/kdc_audit.c b/src/kdc/kdc_audit.c
-index c9a7f9f9d..f40913dc8 100644
---- a/src/kdc/kdc_audit.c
-+++ b/src/kdc/kdc_audit.c
-@@ -146,7 +146,7 @@ kau_make_tkt_id(krb5_context context,
- {
-     krb5_error_code ret = 0;
-     char *hash = NULL, *ptr;
--    krb5_checksum cksum;
-+    uint8_t hashbytes[K5_SHA256_HASHLEN];
-     unsigned int i;
- 
-     *out = NULL;
-@@ -154,19 +154,18 @@ kau_make_tkt_id(krb5_context context,
-     if (ticket == NULL)
-         return EINVAL;
- 
--    ret = krb5_c_make_checksum(context, CKSUMTYPE_RSA_MD5, NULL, 0,
--                               &ticket->enc_part.ciphertext, &cksum);
-+    ret = k5_sha256(&ticket->enc_part.ciphertext, 1, hashbytes);
-     if (ret)
-         return ret;
- 
--    hash = k5alloc(cksum.length * 2 + 1, &ret);
--    if (hash != NULL) {
--        for (i = 0, ptr = hash; i < cksum.length; i++, ptr += 2)
--            snprintf(ptr, 3, "%02X", cksum.contents[i]);
--        *ptr = '\0';
--        *out = hash;
--    }
--    krb5_free_checksum_contents(context, &cksum);
-+    hash = k5alloc(sizeof(hashbytes) * 2 + 1, &ret);
-+    if (hash == NULL)
-+        return ret;
-+
-+    for (i = 0, ptr = hash; i < sizeof(hashbytes); i++, ptr += 2)
-+        snprintf(ptr, 3, "%02X", hashbytes[i]);
-+    *ptr = '\0';
-+    *out = hash;
- 
-     return 0;
- }
diff --git a/SOURCES/Use-k5_buf_init_dynamic_zap-where-appropriate.patch b/SOURCES/Use-k5_buf_init_dynamic_zap-where-appropriate.patch
deleted file mode 100644
index 3d3bcd8..0000000
--- a/SOURCES/Use-k5_buf_init_dynamic_zap-where-appropriate.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From c5df16a88027d7f9b6eb53b1c3fa949d6538616b Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Mon, 26 Mar 2018 11:24:49 -0400
-Subject: [PATCH] Use k5_buf_init_dynamic_zap where appropriate
-
-(cherry picked from commit 9172599008f3a6790d4a9a67acff58049742dcb6)
----
- src/lib/krb5/ccache/cc_file.c    | 4 ++--
- src/lib/krb5/ccache/cc_keyring.c | 2 +-
- src/util/support/utf8_conv.c     | 4 +++-
- 3 files changed, 6 insertions(+), 4 deletions(-)
-
-diff --git a/src/lib/krb5/ccache/cc_file.c b/src/lib/krb5/ccache/cc_file.c
-index 6789c09e1..9263a0054 100644
---- a/src/lib/krb5/ccache/cc_file.c
-+++ b/src/lib/krb5/ccache/cc_file.c
-@@ -758,7 +758,7 @@ fcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor,
- 
-     memset(creds, 0, sizeof(*creds));
-     k5_cc_mutex_lock(context, &data->lock);
--    k5_buf_init_dynamic(&buf);
-+    k5_buf_init_dynamic_zap(&buf);
- 
-     ret = krb5_lock_file(context, fileno(fcursor->fp), KRB5_LOCKMODE_SHARED);
-     if (ret)
-@@ -982,7 +982,7 @@ fcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds)
-         goto cleanup;
- 
-     /* Marshal the cred and write it to the file with a single append write. */
--    k5_buf_init_dynamic(&buf);
-+    k5_buf_init_dynamic_zap(&buf);
-     k5_marshal_cred(&buf, version, creds);
-     ret = k5_buf_status(&buf);
-     if (ret)
-diff --git a/src/lib/krb5/ccache/cc_keyring.c b/src/lib/krb5/ccache/cc_keyring.c
-index fba710b1b..8419f6ebf 100644
---- a/src/lib/krb5/ccache/cc_keyring.c
-+++ b/src/lib/krb5/ccache/cc_keyring.c
-@@ -1295,7 +1295,7 @@ krcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds)
-         goto errout;
- 
-     /* Serialize credential using the file ccache version 4 format. */
--    k5_buf_init_dynamic(&buf);
-+    k5_buf_init_dynamic_zap(&buf);
-     k5_marshal_cred(&buf, 4, creds);
-     ret = k5_buf_status(&buf);
-     if (ret)
-diff --git a/src/util/support/utf8_conv.c b/src/util/support/utf8_conv.c
-index 5cfc2c512..08cef4168 100644
---- a/src/util/support/utf8_conv.c
-+++ b/src/util/support/utf8_conv.c
-@@ -99,7 +99,9 @@ k5_utf8_to_utf16le(const char *utf8, uint8_t **utf16_out, size_t *nbytes_out)
-     *utf16_out = NULL;
-     *nbytes_out = 0;
- 
--    k5_buf_init_dynamic(&buf);
-+    /* UTF-16 conversion is used for RC4 string-to-key, so treat this data as
-+     * sensitive. */
-+    k5_buf_init_dynamic_zap(&buf);
- 
-     /* Examine next UTF-8 character. */
-     while (*utf8 != '\0') {
diff --git a/SOURCES/Use-libkrb5support-hex-functions-where-appropriate.patch b/SOURCES/Use-libkrb5support-hex-functions-where-appropriate.patch
deleted file mode 100644
index eab05bc..0000000
--- a/SOURCES/Use-libkrb5support-hex-functions-where-appropriate.patch
+++ /dev/null
@@ -1,869 +0,0 @@
-From 19109505ad04efdfd70df3ee922e22bcf5a294f3 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Mon, 19 Feb 2018 00:52:35 -0500
-Subject: [PATCH] Use libkrb5support hex functions where appropriate
-
-(cherry picked from commit b0c700608be7455041a8afc0e4502e8783ee7f30)
----
- src/kadmin/dbutil/deps                        | 16 ++---
- src/kadmin/dbutil/tabdump.c                   | 19 +++---
- src/kadmin/ktutil/deps                        | 13 ++--
- src/kadmin/ktutil/ktutil_funcs.c              | 30 ++++-----
- src/lib/crypto/crypto_tests/deps              | 39 ++++++-----
- src/lib/crypto/crypto_tests/t_cksum.c         | 35 +++-------
- src/lib/crypto/crypto_tests/t_crc.c           | 28 ++------
- src/lib/crypto/crypto_tests/t_hmac.c          | 34 +++++-----
- src/plugins/kdb/ldap/ldap_util/deps           | 18 ++---
- .../kdb/ldap/ldap_util/kdb5_ldap_services.c   | 32 +++------
- .../kdb/ldap/ldap_util/kdb5_ldap_services.h   |  2 -
- src/plugins/kdb/ldap/libkdb_ldap/deps         | 19 +++---
- .../kdb/ldap/libkdb_ldap/ldap_service_stash.c | 65 +++----------------
- .../kdb/ldap/libkdb_ldap/ldap_service_stash.h |  3 -
- .../kdb/ldap/libkdb_ldap/libkdb_ldap.exports  |  1 -
- src/slave/deps                                | 15 +++--
- src/slave/kproplog.c                          | 11 ++--
- src/tests/gssapi/deps                         | 14 ++--
- src/tests/gssapi/t_prf.c                      | 13 ++--
- 19 files changed, 152 insertions(+), 255 deletions(-)
-
-diff --git a/src/kadmin/dbutil/deps b/src/kadmin/dbutil/deps
-index 4dcc33628..8b0965aac 100644
---- a/src/kadmin/dbutil/deps
-+++ b/src/kadmin/dbutil/deps
-@@ -185,14 +185,14 @@ $(OUTPRE)tabdump.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-   $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \
-   $(top_srcdir)/include/iprop_hdr.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/kdb.h $(top_srcdir)/include/kdb_log.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 kdb5_util.h tabdump.c \
--  tdumputil.h
-+  $(top_srcdir)/include/k5-hex.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/kdb.h \
-+  $(top_srcdir)/include/kdb_log.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 \
-+  kdb5_util.h tabdump.c tdumputil.h
- $(OUTPRE)tdumputil.$(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 \
-diff --git a/src/kadmin/dbutil/tabdump.c b/src/kadmin/dbutil/tabdump.c
-index fb36b060a..2f313dbb0 100644
---- a/src/kadmin/dbutil/tabdump.c
-+++ b/src/kadmin/dbutil/tabdump.c
-@@ -32,6 +32,7 @@
- 
- #include <k5-int.h>
- #include "k5-platform.h"        /* for asprintf */
-+#include "k5-hex.h"
- 
- #include <limits.h>
- #include <stdio.h>
-@@ -230,9 +231,7 @@ static int
- write_data(struct rec_args *args, krb5_data *data)
- {
-     int ret;
--    char *p;
--    size_t i;
--    struct k5buf buf;
-+    char *hex;
-     struct rechandle *h = args->rh;
-     struct tdopts *opts = args->opts;
- 
-@@ -241,17 +240,15 @@ write_data(struct rec_args *args, krb5_data *data)
-             return -1;
-         return 0;
-     }
--    k5_buf_init_dynamic(&buf);
--    p = data->data;
--    for (i = 0; i < data->length; i++)
--        k5_buf_add_fmt(&buf, "%02x", (unsigned char)p[i]);
- 
--    if (buf.data == NULL) {
--        errno = ENOMEM;
-+    ret = k5_hex_encode(data->data, data->length, FALSE, &hex);
-+    if (ret) {
-+        errno = ret;
-         return -1;
-     }
--    ret = writefield(h, "%s", (char *)buf.data);
--    k5_buf_free(&buf);
-+
-+    ret = writefield(h, "%s", hex);
-+    free(hex);
-     return ret;
- }
- 
-diff --git a/src/kadmin/ktutil/deps b/src/kadmin/ktutil/deps
-index 4df399924..5863e63c7 100644
---- a/src/kadmin/ktutil/deps
-+++ b/src/kadmin/ktutil/deps
-@@ -18,9 +18,10 @@ $(OUTPRE)ktutil_funcs.$(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 ktutil.h ktutil_funcs.c
-+  $(top_srcdir)/include/k5-hex.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 \
-+  ktutil.h ktutil_funcs.c
-diff --git a/src/kadmin/ktutil/ktutil_funcs.c b/src/kadmin/ktutil/ktutil_funcs.c
-index 7a3aa0dca..5843e24b7 100644
---- a/src/kadmin/ktutil/ktutil_funcs.c
-+++ b/src/kadmin/ktutil/ktutil_funcs.c
-@@ -29,6 +29,7 @@
-  */
- 
- #include "k5-int.h"
-+#include "k5-hex.h"
- #include "ktutil.h"
- #include <string.h>
- #include <ctype.h>
-@@ -106,9 +107,8 @@ krb5_error_code ktutil_add(context, list, princ_str, kvno,
-     krb5_keyblock key;
-     char buf[BUFSIZ];
-     char promptstr[1024];
--
--    char *cp;
--    int i, tmp;
-+    uint8_t *keybytes;
-+    size_t keylen;
-     unsigned int pwsize = BUFSIZ;
- 
-     retval = krb5_parse_name(context, princ_str, &princ);
-@@ -199,24 +199,18 @@ krb5_error_code ktutil_add(context, list, princ_str, kvno,
-             goto cleanup;
-         }
- 
--        lp->entry->key.enctype = enctype;
--        lp->entry->key.contents = (krb5_octet *) malloc((strlen(buf) + 1) / 2);
--        if (!lp->entry->key.contents) {
--            retval = ENOMEM;
-+        retval = k5_hex_decode(buf, &keybytes, &keylen);
-+        if (retval) {
-+            if (retval == EINVAL) {
-+                fprintf(stderr, _("addent: Illegal character in key.\n"));
-+                retval = 0;
-+            }
-             goto cleanup;
-         }
- 
--        i = 0;
--        for (cp = buf; *cp; cp += 2) {
--            if (!isxdigit((int) cp[0]) || !isxdigit((int) cp[1])) {
--                fprintf(stderr, _("addent: Illegal character in key.\n"));
--                retval = 0;
--                goto cleanup;
--            }
--            sscanf(cp, "%02x", &tmp);
--            lp->entry->key.contents[i++] = (krb5_octet) tmp;
--        }
--        lp->entry->key.length = i;
-+        lp->entry->key.enctype = enctype;
-+        lp->entry->key.contents = keybytes;
-+        lp->entry->key.length = keylen;
-     }
-     lp->entry->principal = princ;
-     lp->entry->vno = kvno;
-diff --git a/src/lib/crypto/crypto_tests/deps b/src/lib/crypto/crypto_tests/deps
-index bc5422a06..5d94a593d 100644
---- a/src/lib/crypto/crypto_tests/deps
-+++ b/src/lib/crypto/crypto_tests/deps
-@@ -73,12 +73,13 @@ $(OUTPRE)t_hmac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-   $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
-   $(srcdir)/../krb/crypto_int.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 t_hmac.c
-+  $(top_srcdir)/include/k5-hex.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 \
-+  t_hmac.c
- $(OUTPRE)t_pkcs5.$(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 \
-@@ -143,12 +144,13 @@ $(OUTPRE)t_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 t_cksum.c
-+  $(top_srcdir)/include/k5-hex.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 \
-+  t_cksum.c
- $(OUTPRE)t_cksums.$(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 \
-@@ -165,12 +167,13 @@ $(OUTPRE)t_crc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-   $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
-   $(srcdir)/../krb/crypto_int.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 t_crc.c
-+  $(top_srcdir)/include/k5-hex.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 \
-+  t_crc.c
- $(OUTPRE)t_mddriver.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-   $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
-   $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
-diff --git a/src/lib/crypto/crypto_tests/t_cksum.c b/src/lib/crypto/crypto_tests/t_cksum.c
-index 2200fe76e..0edaeb850 100644
---- a/src/lib/crypto/crypto_tests/t_cksum.c
-+++ b/src/lib/crypto/crypto_tests/t_cksum.c
-@@ -27,6 +27,7 @@
- /* Test checksum and checksum compatability for rsa-md[4,5]-des. */
- 
- #include "k5-int.h"
-+#include "k5-hex.h"
- 
- #define MD5_K5BETA_COMPAT
- #define MD4_K5BETA_COMPAT
-@@ -50,29 +51,6 @@ print_checksum(char *text, int number, char *message, krb5_checksum *checksum)
-     printf("\n");
- }
- 
--static void
--parse_hexstring(const char *s, krb5_checksum *cksum)
--{
--    size_t i, len;
--    unsigned int byte;
--    unsigned char *cp;
--
--    len = strlen(s);
--    cp = malloc(len / 2);
--    cksum->contents = cp;
--    if (cp == NULL) {
--        cksum->length = 0;
--        return;
--    }
--    cksum->length = len / 2;
--    for (i = 0; i + 1 < len; i += 2) {
--        sscanf(&s[i], "%2x", &byte);
--        *cp++ = byte;
--    }
--    cksum->checksum_type = CKTYPE;
--    cksum->magic = KV5M_CHECKSUM;
--}
--
- /*
-  * Test the checksum verification of Old Style (tm) and correct RSA-MD[4,5]-DES
-  * checksums.
-@@ -86,6 +64,7 @@ main(argc, argv)
-     char **argv;
- {
-     int                   msgindex;
-+    size_t                len;
-     krb5_boolean          valid;
-     krb5_keyblock         keyblock;
-     krb5_key              key;
-@@ -150,12 +129,14 @@ main(argc, argv)
-         free(checksum.contents);
- 
-         /* Verify a known-good checksum for this plaintext. */
--        parse_hexstring(argv[msgindex+1], &knowncksum);
--        if (knowncksum.contents == NULL) {
--            printf("parse_hexstring failed\n");
--            kret = 1;
-+        kret = k5_hex_decode(argv[msgindex + 1], &knowncksum.contents, &len);
-+        if (kret) {
-+            printf("k5_hex_decode failed\n");
-             break;
-         }
-+        knowncksum.length = len;
-+        knowncksum.checksum_type = CKTYPE;
-+        knowncksum.magic = KV5M_CHECKSUM;
-         kret = krb5_k_verify_checksum(NULL, key, 0, &plaintext, &knowncksum,
-                                       &valid);
-         if (kret != 0) {
-diff --git a/src/lib/crypto/crypto_tests/t_crc.c b/src/lib/crypto/crypto_tests/t_crc.c
-index 190773252..1a35cfba5 100644
---- a/src/lib/crypto/crypto_tests/t_crc.c
-+++ b/src/lib/crypto/crypto_tests/t_crc.c
-@@ -32,6 +32,7 @@
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-+#include <k5-hex.h>
- #include "crypto_int.h"
- 
- #define HEX 1
-@@ -139,31 +140,12 @@ timetest(unsigned int nblk, unsigned int blksiz)
- }
- #endif
- 
--static void gethexstr(char *data, size_t *outlen, unsigned char *outbuf,
--                      size_t buflen)
--{
--    size_t inlen;
--    char *cp, buf[3];
--    long n;
--
--    inlen = strlen(data);
--    *outlen = 0;
--    for (cp = data; (size_t) (cp - data) < inlen; cp += 2) {
--        strncpy(buf, cp, 2);
--        buf[2] = '\0';
--        n = strtol(buf, NULL, 16);
--        outbuf[(*outlen)++] = n;
--        if (*outlen > buflen)
--            break;
--    }
--}
--
- static void
- verify(void)
- {
-     unsigned int i;
-     struct crc_trial trial;
--    unsigned char buf[4];
-+    uint8_t *bytes;
-     size_t len;
-     unsigned long cksum;
-     char *typestr;
-@@ -179,9 +161,11 @@ verify(void)
-             break;
-         case HEX:
-             typestr = "HEX";
--            gethexstr(trial.data, &len, buf, 4);
-+            if (k5_hex_decode(trial.data, &bytes, &len) != 0)
-+                abort();
-             cksum = 0;
--            mit_crc32(buf, len, &cksum);
-+            mit_crc32(bytes, len, &cksum);
-+            free(bytes);
-             break;
-         default:
-             typestr = "BOGUS";
-diff --git a/src/lib/crypto/crypto_tests/t_hmac.c b/src/lib/crypto/crypto_tests/t_hmac.c
-index 8961380ea..93d54828f 100644
---- a/src/lib/crypto/crypto_tests/t_hmac.c
-+++ b/src/lib/crypto/crypto_tests/t_hmac.c
-@@ -34,6 +34,7 @@
- #include <string.h>
- #include <ctype.h>
- 
-+#include <k5-hex.h>
- #include "crypto_int.h"
- 
- #define ASIZE(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0]))
-@@ -136,12 +137,10 @@ static void test_hmac()
- {
-     krb5_keyblock key;
-     krb5_data in, out;
--    char outbuf[20];
--    char stroutbuf[80];
-+    char outbuf[20], *hexdigest;
-     krb5_error_code err;
--    unsigned int i, j;
-+    unsigned int i;
-     int lose = 0;
--    struct k5buf buf;
- 
-     /* RFC 2202 test vector.  */
-     static const struct hmac_test md5tests[] = {
-@@ -151,13 +150,13 @@ static void test_hmac()
-                 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb,
-             },
-             8, "Hi There",
--            "0x9294727a3638bb1c13f48ef8158bfc9d"
-+            "9294727a3638bb1c13f48ef8158bfc9d"
-         },
- 
-         {
-             4, "Jefe",
-             28, "what do ya want for nothing?",
--            "0x750c783e6ab0b503eaa86e310a5db738"
-+            "750c783e6ab0b503eaa86e310a5db738"
-         },
- 
-         {
-@@ -172,7 +171,7 @@ static void test_hmac()
-                 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-                 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-             },
--            "0x56be34521d144c88dbb8c733f0e8b3f6"
-+            "56be34521d144c88dbb8c733f0e8b3f6"
-         },
- 
-         {
-@@ -188,7 +187,7 @@ static void test_hmac()
-                 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-                 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-             },
--            "0x697eaf0aca3a3aea3a75164746ffaa79"
-+            "697eaf0aca3a3aea3a75164746ffaa79"
-         },
- 
-         {
-@@ -197,7 +196,7 @@ static void test_hmac()
-                 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c
-             },
-             20, "Test With Truncation",
--            "0x56461ef2342edc00f9bab995690efd4c"
-+            "56461ef2342edc00f9bab995690efd4c"
-         },
- 
-         {
-@@ -212,7 +211,7 @@ static void test_hmac()
-                 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-             },
-             54, "Test Using Larger Than Block-Size Key - Hash Key First",
--            "0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd"
-+            "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd"
-         },
- 
-         {
-@@ -228,7 +227,7 @@ static void test_hmac()
-             },
-             73,
-             "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
--            "0x6f630fad67cda0ee1fb1f562db3aa53e"
-+            "6f630fad67cda0ee1fb1f562db3aa53e"
-         },
-     };
- 
-@@ -246,19 +245,16 @@ static void test_hmac()
-             exit(1);
-         }
- 
--        k5_buf_init_fixed(&buf, stroutbuf, sizeof(stroutbuf));
--        k5_buf_add(&buf, "0x");
--        for (j = 0; j < out.length; j++)
--            k5_buf_add_fmt(&buf, "%02x", 0xff & outbuf[j]);
--        if (k5_buf_status(&buf) != 0)
-+        if (k5_hex_encode(out.data, out.length, FALSE, &hexdigest) != 0)
-             abort();
--        if (strcmp(stroutbuf, md5tests[i].hexdigest)) {
-+        if (strcmp(hexdigest, md5tests[i].hexdigest)) {
-             printf("*** CHECK FAILED!\n"
--                   "\tReturned: %s.\n"
--                   "\tExpected: %s.\n", stroutbuf, md5tests[i].hexdigest);
-+                   "\tReturned: 0x%s.\n"
-+                   "\tExpected: 0x%s.\n", hexdigest, md5tests[i].hexdigest);
-             lose++;
-         } else
-             printf("Matches expected result.\n");
-+        free(hexdigest);
-     }
- 
-     /* Do again with SHA-1 tests....  */
-diff --git a/src/plugins/kdb/ldap/ldap_util/deps b/src/plugins/kdb/ldap/ldap_util/deps
-index 75d4dd0cf..be0194c00 100644
---- a/src/plugins/kdb/ldap/ldap_util/deps
-+++ b/src/plugins/kdb/ldap/ldap_util/deps
-@@ -89,15 +89,15 @@ $(OUTPRE)kdb5_ldap_services.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-   $(srcdir)/../libkdb_ldap/ldap_krbcontainer.h $(srcdir)/../libkdb_ldap/ldap_misc.h \
-   $(srcdir)/../libkdb_ldap/ldap_realm.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/kdb.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 \
--  $(top_srcdir)/lib/kdb/kdb5.h kdb5_ldap_list.h kdb5_ldap_policy.h \
--  kdb5_ldap_realm.h kdb5_ldap_services.c kdb5_ldap_services.h \
--  kdb5_ldap_util.h
-+  $(top_srcdir)/include/k5-hex.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/kdb.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 $(top_srcdir)/lib/kdb/kdb5.h \
-+  kdb5_ldap_list.h kdb5_ldap_policy.h kdb5_ldap_realm.h \
-+  kdb5_ldap_services.c kdb5_ldap_services.h kdb5_ldap_util.h
- $(OUTPRE)getdate.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-   $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \
-   getdate.c
-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 3d6994c67..ce038fc3d 100644
---- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
-+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
-@@ -37,6 +37,7 @@
-  */
- 
- #include <k5-int.h>
-+#include <k5-hex.h>
- #include "kdb5_ldap_util.h"
- #include "kdb5_ldap_list.h"
- 
-@@ -96,11 +97,10 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
-     char *service_object = NULL;
-     char *file_name = NULL, *tmp_file = NULL;
-     char passwd[MAX_SERVICE_PASSWD_LEN];
--    char *str = NULL;
-+    char *str = NULL, *hexpasswd = NULL;
-     char line[MAX_LEN];
-     FILE *pfile = NULL;
-     krb5_boolean print_usage = FALSE;
--    krb5_data hexpasswd = {0, 0, NULL};
-     mode_t old_mode = 0;
- 
-     /*
-@@ -183,21 +183,12 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
-     }
- 
-     /* Convert the password to hexadecimal */
--    {
--        krb5_data pwd;
--
--        pwd.length = passwd_len;
--        pwd.data = passwd;
--
--        ret = tohex(pwd, &hexpasswd);
--        if (ret != 0) {
--            com_err(me, ret,
--                    _("Failed to convert the password to hexadecimal"));
--            memset(passwd, 0, passwd_len);
--            goto cleanup;
--        }
-+    ret = k5_hex_encode(passwd, passwd_len, FALSE, &hexpasswd);
-+    zap(passwd, passwd_len);
-+    if (ret != 0) {
-+        com_err(me, ret, _("Failed to convert the password to hexadecimal"));
-+        goto cleanup;
-     }
--    memset(passwd, 0, passwd_len);
- 
-     /* TODO: file lock for the service password file */
- 
-@@ -225,7 +216,7 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
-     if (str == NULL) {
-         if (feof(pfile)) {
-             /* If the service object dn is not present in the service password file */
--            if (fprintf(pfile, "%s#{HEX}%s\n", service_object, hexpasswd.data) < 0) {
-+            if (fprintf(pfile, "%s#{HEX}%s\n", service_object, hexpasswd) < 0) {
-                 com_err(me, errno,
-                         _("Failed to write service object password to file"));
-                 fclose(pfile);
-@@ -277,7 +268,7 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
-         while (fgets(line, MAX_LEN, pfile) != NULL) {
-             if (((str = strstr(line, service_object)) != NULL) &&
-                 (line[strlen(service_object)] == '#')) {
--                if (fprintf(newfile, "%s#{HEX}%s\n", service_object, hexpasswd.data) < 0) {
-+                if (fprintf(newfile, "%s#{HEX}%s\n", service_object, hexpasswd) < 0) {
-                     com_err(me, errno, _("Failed to write service object "
-                                          "password to file"));
-                     fclose(newfile);
-@@ -322,10 +313,7 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
- 
- cleanup:
- 
--    if (hexpasswd.length != 0) {
--        memset(hexpasswd.data, 0, hexpasswd.length);
--        free(hexpasswd.data);
--    }
-+    zapfreestr(hexpasswd);
- 
-     if (service_object)
-         free(service_object);
-diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h
-index cf652c578..08af62e17 100644
---- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h
-+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h
-@@ -32,6 +32,4 @@
- #define MAX_LEN                 1024
- #define MAX_SERVICE_PASSWD_LEN  256
- 
--extern int tohex(krb5_data, krb5_data *);
--
- extern void kdb5_ldap_stash_service_password(int argc, char **argv);
-diff --git a/src/plugins/kdb/ldap/libkdb_ldap/deps b/src/plugins/kdb/ldap/libkdb_ldap/deps
-index 1ff28553f..afca604dc 100644
---- a/src/plugins/kdb/ldap/libkdb_ldap/deps
-+++ b/src/plugins/kdb/ldap/libkdb_ldap/deps
-@@ -220,15 +220,16 @@ ldap_service_stash.so ldap_service_stash.po $(OUTPRE)ldap_service_stash.$(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/kdb.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 $(top_srcdir)/lib/kdb/kdb5.h \
--  kdb_ldap.h ldap_handle.h ldap_krbcontainer.h ldap_main.h \
--  ldap_misc.h ldap_realm.h ldap_service_stash.c ldap_service_stash.h
-+  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-hex.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/kdb.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 \
-+  $(top_srcdir)/lib/kdb/kdb5.h kdb_ldap.h ldap_handle.h \
-+  ldap_krbcontainer.h ldap_main.h ldap_misc.h ldap_realm.h \
-+  ldap_service_stash.c ldap_service_stash.h
- kdb_xdr.so kdb_xdr.po $(OUTPRE)kdb_xdr.$(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 \
-diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c
-index 87a2118ff..cb30f4a7f 100644
---- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c
-+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c
-@@ -31,16 +31,16 @@
- #include "ldap_main.h"
- #include "kdb_ldap.h"
- #include "ldap_service_stash.h"
-+#include <k5-hex.h>
- #include <ctype.h>
- 
- /* Decode a password of the form {HEX}<hexstring>. */
- static krb5_error_code
- dec_password(krb5_context context, const char *str, char **password_out)
- {
-+    krb5_error_code ret;
-+    uint8_t *bytes;
-     size_t len;
--    const unsigned char *p;
--    unsigned char *password, *q;
--    unsigned int k;
- 
-     *password_out = NULL;
- 
-@@ -48,30 +48,15 @@ dec_password(krb5_context context, const char *str, char **password_out)
-         k5_setmsg(context, EINVAL, _("Not a hexadecimal password"));
-         return EINVAL;
-     }
--    str += 5;
- 
--    len = strlen(str);
--    if (len % 2 != 0) {
--        k5_setmsg(context, EINVAL, _("Password corrupt"));
--        return EINVAL;
-+    ret = k5_hex_decode(str + 5, &bytes, &len);
-+    if (ret) {
-+        if (ret == EINVAL)
-+            k5_setmsg(context, ret, _("Password corrupt"));
-+        return ret;
-     }
- 
--    q = password = malloc(len / 2 + 1);
--    if (password == NULL)
--        return ENOMEM;
--
--    for (p = (unsigned char *)str; *p != '\0'; p += 2) {
--        if (!isxdigit(*p) || !isxdigit(p[1])) {
--            free(password);
--            k5_setmsg(context, EINVAL, _("Password corrupt"));
--            return EINVAL;
--        }
--        sscanf((char *)p, "%2x", &k);
--        *q++ = k;
--    }
--    *q = '\0';
--
--    *password_out = (char *)password;
-+    *password_out = (char *)bytes;
-     return 0;
- }
- 
-@@ -128,35 +113,3 @@ krb5_ldap_readpassword(krb5_context context, const char *filename,
-     /* Extract the plain password information. */
-     return dec_password(context, val, password_out);
- }
--
--/* Encodes a sequence of bytes in hexadecimal */
--
--int
--tohex(krb5_data in, krb5_data *ret)
--{
--    unsigned int       i=0;
--    int                err = 0;
--
--    ret->length = 0;
--    ret->data = NULL;
--
--    ret->data = malloc((unsigned int)in.length * 2 + 1 /*Null termination */);
--    if (ret->data == NULL) {
--        err = ENOMEM;
--        goto cleanup;
--    }
--    ret->length = in.length * 2;
--    ret->data[ret->length] = 0;
--
--    for (i = 0; i < in.length; i++)
--        snprintf(ret->data + 2 * i, 3, "%02x", in.data[i] & 0xff);
--
--cleanup:
--
--    if (ret->length == 0) {
--        free(ret->data);
--        ret->data = NULL;
--    }
--
--    return err;
--}
-diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h b/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h
-index dbf62443a..03cf9a1f7 100644
---- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h
-+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h
-@@ -37,7 +37,4 @@ krb5_error_code
- krb5_ldap_readpassword(krb5_context context, const char *filename,
-                        const char *name, char **password_out);
- 
--int
--tohex(krb5_data, krb5_data *);
--
- #endif
-diff --git a/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports b/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports
-index 2342f1db8..5376d3453 100644
---- a/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports
-+++ b/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports
-@@ -1,4 +1,3 @@
--tohex
- krb5_ldap_open
- krb5_ldap_close
- krb5_ldap_db_init
-diff --git a/src/slave/deps b/src/slave/deps
-index c3677a5e1..c0f558ecd 100644
---- a/src/slave/deps
-+++ b/src/slave/deps
-@@ -64,10 +64,11 @@ $(OUTPRE)kproplog.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-   $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \
-   $(top_srcdir)/include/iprop_hdr.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/kdb.h $(top_srcdir)/include/kdb_log.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 kproplog.c
-+  $(top_srcdir)/include/k5-hex.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/kdb.h \
-+  $(top_srcdir)/include/kdb_log.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 \
-+  kproplog.c
-diff --git a/src/slave/kproplog.c b/src/slave/kproplog.c
-index 4f19eeb8c..d4aed7ba6 100644
---- a/src/slave/kproplog.c
-+++ b/src/slave/kproplog.c
-@@ -9,6 +9,7 @@
-  */
- 
- #include "k5-int.h"
-+#include "k5-hex.h"
- #include <locale.h>
- #include <sys/types.h>
- #include <sys/mman.h>
-@@ -106,15 +107,15 @@ print_deltat(uint32_t *deltat)
- static void
- print_hex(const char *tag, utf8str_t *str)
- {
--    unsigned int i;
-     unsigned int len;
-+    char *hex;
- 
-     len = str->utf8str_t_len;
- 
--    printf("\t\t\t%s(%d): 0x", tag, len);
--    for (i = 0; i < len; i++)
--        printf("%02x", (krb5_octet)str->utf8str_t_val[i]);
--    printf("\n");
-+    if (k5_hex_encode(str->utf8str_t_val, len, FALSE, &hex) != 0)
-+        abort();
-+    printf("\t\t\t%s(%d): 0x%s\n", tag, len, hex);
-+    free(hex);
- }
- 
- /* Display string primitive. */
-diff --git a/src/tests/gssapi/deps b/src/tests/gssapi/deps
-index b784deb63..0b50d9ed3 100644
---- a/src/tests/gssapi/deps
-+++ b/src/tests/gssapi/deps
-@@ -149,13 +149,13 @@ $(OUTPRE)t_prf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-   $(srcdir)/../../lib/gssapi/krb5/gssapiP_krb5.h $(srcdir)/../../lib/gssapi/krb5/gssapi_krb5.h \
-   $(srcdir)/../../lib/gssapi/mechglue/mechglue.h $(srcdir)/../../lib/gssapi/mechglue/mglueP.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 \
--  common.h t_prf.c
-+  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-hex.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 common.h t_prf.c
- $(OUTPRE)t_s4u.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \
-   $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \
-   $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \
-diff --git a/src/tests/gssapi/t_prf.c b/src/tests/gssapi/t_prf.c
-index 2c8c85188..6a698ce0f 100644
---- a/src/tests/gssapi/t_prf.c
-+++ b/src/tests/gssapi/t_prf.c
-@@ -24,6 +24,7 @@
-  */
- 
- #include "k5-int.h"
-+#include "k5-hex.h"
- #include "common.h"
- #include "mglueP.h"
- #include "gssapiP_krb5.h"
-@@ -109,12 +110,14 @@ static struct {
- static size_t
- fromhex(const char *hexstr, unsigned char *out)
- {
--    const char *p;
--    size_t count;
-+    uint8_t *bytes;
-+    size_t len;
- 
--    for (p = hexstr, count = 0; *p != '\0'; p += 2, count++)
--        sscanf(p, "%2hhx", &out[count]);
--    return count;
-+    if (k5_hex_decode(hexstr, &bytes, &len) != 0)
-+        abort();
-+    memcpy(out, bytes, len);
-+    free(bytes);
-+    return len;
- }
- 
- int
diff --git a/SOURCES/Use-openssl-s-PRNG-in-FIPS-mode.patch b/SOURCES/Use-openssl-s-PRNG-in-FIPS-mode.patch
new file mode 100644
index 0000000..632859f
--- /dev/null
+++ b/SOURCES/Use-openssl-s-PRNG-in-FIPS-mode.patch
@@ -0,0 +1,41 @@
+From 196ee40d489e4e6a72232a3cdbb7af19a72362b3 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Fri, 4 Jan 2019 17:00:15 -0500
+Subject: [PATCH] Use openssl's PRNG in FIPS mode
+
+(cherry picked from commit 31277d79675a76612015ea00d420b41b9a232d5a)
+---
+ src/lib/crypto/krb/prng.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+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/SOURCES/Zap-copy-of-secret-in-RC4-string-to-key.patch b/SOURCES/Zap-copy-of-secret-in-RC4-string-to-key.patch
deleted file mode 100644
index 7502c25..0000000
--- a/SOURCES/Zap-copy-of-secret-in-RC4-string-to-key.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 55a8161c3f5238df522447499a38bf2e9497b074 Mon Sep 17 00:00:00 2001
-From: Dylan Gray <35609490+Dylan-MSFT@users.noreply.github.com>
-Date: Fri, 13 Jul 2018 15:09:01 -0700
-Subject: [PATCH] Zap copy of secret in RC4 string-to-key
-
-Commit b8814745049b5f401e3ae39a81dc1e14598ae48c (ticket 8576) added a
-zero-terminated copy of the input string in
-krb5int_arcfour_string_to_key().  This copy should be zeroed when
-freed as the input string typically contains a password.
-
-[ghudson@mit.edu: rewrote commit message]
-
-ticket: 8713 (new)
----
- src/lib/crypto/krb/s2k_rc4.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/lib/crypto/krb/s2k_rc4.c b/src/lib/crypto/krb/s2k_rc4.c
-index 081a91217..f7e699d60 100644
---- a/src/lib/crypto/krb/s2k_rc4.c
-+++ b/src/lib/crypto/krb/s2k_rc4.c
-@@ -25,7 +25,7 @@ krb5int_arcfour_string_to_key(const struct krb5_keytypes *ktp,
-     if (utf8 == NULL)
-         return err;
-     err = k5_utf8_to_utf16le(utf8, &copystr, &copystrlen);
--    free(utf8);
-+    zapfree(utf8, string->length);
-     if (err)
-         return err;
- 
diff --git a/SOURCES/Zap-data-when-freeing-krb5_spake_factor.patch b/SOURCES/Zap-data-when-freeing-krb5_spake_factor.patch
deleted file mode 100644
index 9ce2462..0000000
--- a/SOURCES/Zap-data-when-freeing-krb5_spake_factor.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 5d970e16e768a134e65ee7cf367b8f34a80e0980 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Tue, 27 Mar 2018 15:42:28 -0400
-Subject: [PATCH] Zap data when freeing krb5_spake_factor
-
-krb5_spake_factor structures will sometimes hold sensitive data when
-second-factor SPAKE is implemented, so should be zapped when freed.
-
-ticket: 8647
-(cherry picked from commit 9cc94a3f1ce06a4430f684300a747ec079102403)
----
- src/lib/krb5/krb/kfree.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/src/lib/krb5/krb/kfree.c b/src/lib/krb5/krb/kfree.c
-index e1ea1494a..71e7fcad0 100644
---- a/src/lib/krb5/krb/kfree.c
-+++ b/src/lib/krb5/krb/kfree.c
-@@ -897,7 +897,9 @@ k5_free_spake_factor(krb5_context context, krb5_spake_factor *val)
- {
-     if (val == NULL)
-         return;
--    krb5_free_data(context, val->data);
-+    if (val->data != NULL)
-+        zapfree(val->data->data, val->data->length);
-+    free(val->data);
-     free(val);
- }
- 
diff --git a/SOURCES/krb5-1.11-kpasswdtest.patch b/SOURCES/krb5-1.11-kpasswdtest.patch
index ddd3ec2..7da7384 100644
--- a/SOURCES/krb5-1.11-kpasswdtest.patch
+++ b/SOURCES/krb5-1.11-kpasswdtest.patch
@@ -1,4 +1,4 @@
-From fc2953ce9ce06ff896b1687e1c0cc9b8a4357d09 Mon Sep 17 00:00:00 2001
+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
diff --git a/SOURCES/krb5-1.11-run_user_0.patch b/SOURCES/krb5-1.11-run_user_0.patch
index febb3b3..7a38d43 100644
--- a/SOURCES/krb5-1.11-run_user_0.patch
+++ b/SOURCES/krb5-1.11-run_user_0.patch
@@ -1,4 +1,4 @@
-From b0adf9a65d5c22a77cf957ceb1c298baff01555d Mon Sep 17 00:00:00 2001
+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
diff --git a/SOURCES/krb5-1.12-api.patch b/SOURCES/krb5-1.12-api.patch
index 9eba2ff..4e42414 100644
--- a/SOURCES/krb5-1.12-api.patch
+++ b/SOURCES/krb5-1.12-api.patch
@@ -1,4 +1,4 @@
-From abb19d2d2eac5f9f6e4a1bf26f59f3a62143dab9 Mon Sep 17 00:00:00 2001
+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
diff --git a/SOURCES/krb5-1.12-ksu-path.patch b/SOURCES/krb5-1.12-ksu-path.patch
index 19b9e73..25b805a 100644
--- a/SOURCES/krb5-1.12-ksu-path.patch
+++ b/SOURCES/krb5-1.12-ksu-path.patch
@@ -1,4 +1,4 @@
-From 7f076496c7441cd108929aa05dbe009f34054bf5 Mon Sep 17 00:00:00 2001
+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
diff --git a/SOURCES/krb5-1.12-ktany.patch b/SOURCES/krb5-1.12-ktany.patch
index de59827..26d36df 100644
--- a/SOURCES/krb5-1.12-ktany.patch
+++ b/SOURCES/krb5-1.12-ktany.patch
@@ -1,4 +1,4 @@
-From 01acbf3cbd60bd460e6ec6702589451d19c89933 Mon Sep 17 00:00:00 2001
+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
diff --git a/SOURCES/krb5-1.12.1-pam.patch b/SOURCES/krb5-1.12.1-pam.patch
index 97c1e8f..c5b5e78 100644
--- a/SOURCES/krb5-1.12.1-pam.patch
+++ b/SOURCES/krb5-1.12.1-pam.patch
@@ -1,4 +1,4 @@
-From 4cbb4325a86d1d71fa45d254221ec460c41b434d Mon Sep 17 00:00:00 2001
+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
@@ -28,10 +28,10 @@ changes we're proposing for how it handles cache collections.
  create mode 100644 src/clients/ksu/pam.h
 
 diff --git a/src/aclocal.m4 b/src/aclocal.m4
-index d6d1279c3..5c9c13e5f 100644
+index 3752d9bd5..340546d80 100644
 --- a/src/aclocal.m4
 +++ b/src/aclocal.m4
-@@ -1696,3 +1696,70 @@ AC_DEFUN(KRB5_AC_PERSISTENT_KEYRING,[
+@@ -1697,3 +1697,70 @@ AC_DEFUN(KRB5_AC_PERSISTENT_KEYRING,[
        ]))
  ])dnl
  dnl
@@ -141,7 +141,7 @@ index b2fcbf240..5755bb58a 100644
  clean:
  	$(RM) ksu
 diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c
-index 7ff676ca7..c6321c01b 100644
+index d9596d948..ec06788bc 100644
 --- a/src/clients/ksu/main.c
 +++ b/src/clients/ksu/main.c
 @@ -26,6 +26,7 @@
@@ -171,7 +171,7 @@ index 7ff676ca7..c6321c01b 100644
  /***********/
  
  #define KS_TEMPORARY_CACHE "MEMORY:_ksu"
-@@ -515,6 +521,23 @@ main (argc, argv)
+@@ -528,6 +534,23 @@ main (argc, argv)
                 prog_name,target_user,client_name,
                 source_user,ontty());
  
@@ -195,7 +195,7 @@ index 7ff676ca7..c6321c01b 100644
          /* Run authorization as target.*/
          if (krb5_seteuid(target_uid)) {
              com_err(prog_name, errno, _("while switching to target for "
-@@ -575,6 +598,24 @@ main (argc, argv)
+@@ -588,6 +611,24 @@ main (argc, argv)
  
              exit(1);
          }
@@ -220,7 +220,7 @@ index 7ff676ca7..c6321c01b 100644
      }
  
      if( some_rest_copy){
-@@ -632,6 +673,30 @@ main (argc, argv)
+@@ -645,6 +686,30 @@ main (argc, argv)
          exit(1);
      }
  
@@ -251,7 +251,7 @@ index 7ff676ca7..c6321c01b 100644
      /* set permissions */
      if (setgid(target_pwd->pw_gid) < 0) {
          perror("ksu: setgid");
-@@ -729,7 +794,7 @@ main (argc, argv)
+@@ -742,7 +807,7 @@ main (argc, argv)
          fprintf(stderr, "program to be execed %s\n",params[0]);
      }
  
@@ -260,7 +260,7 @@ index 7ff676ca7..c6321c01b 100644
          execv(params[0], params);
          com_err(prog_name, errno, _("while trying to execv %s"), params[0]);
          sweep_up(ksu_context, cc_target);
-@@ -759,16 +824,35 @@ main (argc, argv)
+@@ -772,16 +837,35 @@ main (argc, argv)
              if (ret_pid == -1) {
                  com_err(prog_name, errno, _("while calling waitpid"));
              }
@@ -756,10 +756,10 @@ index 000000000..0ab76569c
 +void appl_pam_cleanup(void);
 +#endif
 diff --git a/src/configure.in b/src/configure.in
-index 10f45eb12..7288a71ec 100644
+index 61ef738dc..e9a12ac16 100644
 --- a/src/configure.in
 +++ b/src/configure.in
-@@ -1306,6 +1306,8 @@ AC_SUBST([VERTO_VERSION])
+@@ -1352,6 +1352,8 @@ AC_SUBST([VERTO_VERSION])
  
  AC_PATH_PROG(GROFF, groff)
  
diff --git a/SOURCES/krb5-1.13-dirsrv-accountlock.patch b/SOURCES/krb5-1.13-dirsrv-accountlock.patch
index ff5f73e..db48910 100644
--- a/SOURCES/krb5-1.13-dirsrv-accountlock.patch
+++ b/SOURCES/krb5-1.13-dirsrv-accountlock.patch
@@ -1,4 +1,4 @@
-From bd9a3cc0c53f6dc47a124eb6e8f698c7f1d3cd36 Mon Sep 17 00:00:00 2001
+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
@@ -12,10 +12,10 @@ original version filed as RT#5891.
  3 files changed, 29 insertions(+)
 
 diff --git a/src/aclocal.m4 b/src/aclocal.m4
-index 5eeaa2d8a..1fd243094 100644
+index db18226ed..518b1a547 100644
 --- a/src/aclocal.m4
 +++ b/src/aclocal.m4
-@@ -1677,6 +1677,15 @@ if test "$with_ldap" = yes; then
+@@ -1678,6 +1678,15 @@ if test "$with_ldap" = yes; then
    AC_MSG_NOTICE(enabling OpenLDAP database backend module support)
    OPENLDAP_PLUGIN=yes
  fi
diff --git a/SOURCES/krb5-1.15-beta1-buildconf.patch b/SOURCES/krb5-1.15-beta1-buildconf.patch
index a949727..6d1e151 100644
--- a/SOURCES/krb5-1.15-beta1-buildconf.patch
+++ b/SOURCES/krb5-1.15-beta1-buildconf.patch
@@ -1,4 +1,4 @@
-From 162ba7fbce23d82719956de1b126e48fe676e9d1 Mon Sep 17 00:00:00 2001
+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
@@ -33,7 +33,7 @@ index c17cb5eb5..1891dea99 100755
  	lib_flags="$lib_flags -lkdb5 $KDB5_DB_LIB"
  	library=krb5
 diff --git a/src/config/pre.in b/src/config/pre.in
-index d4714d29a..03f5c8890 100644
+index 917357df9..a8540ae2a 100644
 --- a/src/config/pre.in
 +++ b/src/config/pre.in
 @@ -185,7 +185,7 @@ INSTALL_PROGRAM=@INSTALL_PROGRAM@ $(INSTALL_STRIP)
diff --git a/SOURCES/krb5-1.15.1-selinux-label.patch b/SOURCES/krb5-1.15.1-selinux-label.patch
deleted file mode 100644
index 728c72e..0000000
--- a/SOURCES/krb5-1.15.1-selinux-label.patch
+++ /dev/null
@@ -1,1065 +0,0 @@
-From c79d3881fefb6108306eb56cff62de03897d4bbc 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.15.1-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/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/slave/kpropd.c                            |   9 +
- 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 5c9c13e5f..6257dba40 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
-@@ -1763,3 +1764,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 3f267eb1f..d4714d29a 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=
-@@ -399,7 +400,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 7288a71ec..2b6d5baa7 100644
---- a/src/configure.in
-+++ b/src/configure.in
-@@ -1308,6 +1308,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 e1b1cb040..9378ae047 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 c86e78274..e81bb0a6d 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 aca136f0b..22e926ae4 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;
- 
-@@ -194,7 +203,7 @@ prep_ok_file(krb5_context context, char *file_name, int *fd)
-         return 0;
-     }
- 
--    *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);
-         exit_status++;
-diff --git a/src/kdc/main.c b/src/kdc/main.c
-index f2226da25..ccac3a759 100644
---- a/src/kdc/main.c
-+++ b/src/kdc/main.c
-@@ -873,7 +873,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/lib/kadm5/logger.c b/src/lib/kadm5/logger.c
-index ce79fabf7..c53a5743f 100644
---- a/src/lib/kadm5/logger.c
-+++ b/src/lib/kadm5/logger.c
-@@ -414,7 +414,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");
-@@ -918,7 +918,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 766d3002a..6466417b7 100644
---- a/src/lib/kdb/kdb_log.c
-+++ b/src/lib/kdb/kdb_log.c
-@@ -476,7 +476,7 @@ ulog_map(krb5_context context, const char *logname, uint32_t ulogentries)
-     int ulogfd = -1;
- 
-     if (stat(logname, &st) == -1) {
--        ulogfd = open(logname, O_RDWR | O_CREAT, 0600);
-+        ulogfd = THREEPARAMOPEN(logname, O_RDWR | O_CREAT, 0600);
-         if (ulogfd == -1)
-             return errno;
- 
-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 091f2c43f..ecc97ee2f 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 e97ce5fe5..779f184cb 100644
---- a/src/lib/krb5/os/trace.c
-+++ b/src/lib/krb5/os/trace.c
-@@ -398,7 +398,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 d23587a59..e2825650b 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 022156a5e..3d6994c67 100644
---- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
-+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
-@@ -203,7 +203,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));
-@@ -244,6 +244,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;
- 
-@@ -255,7 +258,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/slave/kpropd.c b/src/slave/kpropd.c
-index d621f108f..99676cc97 100644
---- a/src/slave/kpropd.c
-+++ b/src/slave/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/util/profile/prof_file.c b/src/util/profile/prof_file.c
-index 907c119bb..0f5462aea 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 */
-@@ -423,7 +424,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 0bf0b7a87..58ac2e333 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 \
-@@ -149,7 +150,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.16.1.tar.gz.asc b/SOURCES/krb5-1.16.1.tar.gz.asc
deleted file mode 100644
index 9a11343..0000000
--- a/SOURCES/krb5-1.16.1.tar.gz.asc
+++ /dev/null
@@ -1,17 +0,0 @@
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1
-
-iQIVAwUAWushEwy6CFdfg3LfAQJ+eBAAijTUBfXzCuxCwbDhCFYb1fIbHMkKkTuq
-knFKv0VbALW1qUAj5v35A6GjDam6a33bMvGX8MzbGK/a9IDkpvaaXP/c37V4OfiQ
-MhA6uQl0vxBMoCZqAFEVcWd6+M/0rY0WBZKpXRiZxxuSNPnSXn1l9fQAcrYKGb7I
-YpaAWnzw+cc1k4Xi+GaaSghEYA4dX7TXh1fViJyHaNSESYZjH3J6wEdPm6LtZk6q
-GwJw/ieMQi8djde0AhCbzMHWiaeW3jNPOJmpd3mpY04BAAkzGCyRiYGscxb6ge4u
-ag2fojv7rbnJxDzy9RO0ZP0+fVPDMwInZ5GHPftbraSDFkTH2JBAYFudPsLDAoRK
-FdjLeHpvuU5ifXWrLyshVYYfeXSe0fHz9Xhfhq2/OmfBD6vQl5k86z8IqxNm4ujy
-ziypmTzHFnP/sBKlMgSMdDEKoKZHxevVQM5eJQd1XGexmwogkSPX8mwoEc0q4dtZ
-h5w/fCu4ERA0BihvnQMZCZgwe32pO27ccPc6PqNHffUSLOq74J4gBHeoAoZ+SYPu
-33oG7wxh+8WONzEGujl1lmxHFstij/njg8nULQ6bo6hSZnlMD0gU59mG9seC2jjr
-E4aM4TXd1ixxPzM/cqxfI9SalytwYW0gn7Vuyj3P8xIZ5GQZiTsD7XWJqzb3xHmA
-2JSQt4TK3Cc=
-=9z9K
------END PGP SIGNATURE-----
diff --git a/SOURCES/krb5-1.17-beta1-selinux-label.patch b/SOURCES/krb5-1.17-beta1-selinux-label.patch
new file mode 100644
index 0000000..3f874f5
--- /dev/null
+++ b/SOURCES/krb5-1.17-beta1-selinux-label.patch
@@ -0,0 +1,1065 @@
+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
new file mode 100644
index 0000000..90f7148
--- /dev/null
+++ b/SOURCES/krb5-1.17.tar.gz.asc
@@ -0,0 +1,17 @@
+-----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.3.1-dns.patch b/SOURCES/krb5-1.3.1-dns.patch
index 1af7c12..819bf9f 100644
--- a/SOURCES/krb5-1.3.1-dns.patch
+++ b/SOURCES/krb5-1.3.1-dns.patch
@@ -1,4 +1,4 @@
-From 2338e73d8dced4f85d6b4f5a0f7df21033ac78c1 Mon Sep 17 00:00:00 2001
+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
@@ -9,7 +9,7 @@ We want to be able to use --with-netlib and --enable-dns at the same time.
  1 file changed, 1 insertion(+)
 
 diff --git a/src/aclocal.m4 b/src/aclocal.m4
-index 6257dba40..5eeaa2d8a 100644
+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),
diff --git a/SOURCES/krb5-1.9-debuginfo.patch b/SOURCES/krb5-1.9-debuginfo.patch
index 5b0f5bc..21971ff 100644
--- a/SOURCES/krb5-1.9-debuginfo.patch
+++ b/SOURCES/krb5-1.9-debuginfo.patch
@@ -1,4 +1,4 @@
-From 20bc1c9b1d37138d1a8538f9cef22108c8fabf4f Mon Sep 17 00:00:00 2001
+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
diff --git a/SOURCES/krb5.conf b/SOURCES/krb5.conf
index 99b8859..c45f388 100644
--- a/SOURCES/krb5.conf
+++ b/SOURCES/krb5.conf
@@ -13,7 +13,7 @@ includedir /etc/krb5.conf.d/
     renew_lifetime = 7d
     forwardable = true
     rdns = false
-    pkinit_anchors = /etc/pki/tls/certs/ca-bundle.crt
+    pkinit_anchors = FILE:/etc/pki/tls/certs/ca-bundle.crt
     spake_preauth_groups = edwards25519
 #    default_realm = EXAMPLE.COM
 
diff --git a/SOURCES/noport.c b/SOURCES/noport.c
deleted file mode 100644
index 22088eb..0000000
--- a/SOURCES/noport.c
+++ /dev/null
@@ -1,111 +0,0 @@
-#define _GNU_SOURCE
-#include <sys/socket.h>
-#include <dlfcn.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <netinet/in.h>
-
-static int
-port_is_okay(unsigned short port)
-{
-	char *p, *q;
-	long l;
-
-	p = getenv("NOPORT");
-	while ((p != NULL) && (*p != '\0')) {
-		l = strtol(p, &q, 10);
-		if ((q == NULL) || (q == p)) {
-			break;
-		}
-		if ((*q == '\0') || (*q == ',')) {
-			if (port == l) {
-				errno = ECONNREFUSED;
-				return -1;
-			}
-		}
-		p = q;
-		p += strspn(p, ",");
-	}
-	return 0;
-}
-
-int
-connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
-{
-	unsigned short port;
-	static int (*next_connect)(int, const struct sockaddr *, socklen_t);
-
-	if (next_connect == NULL) {
-		next_connect = dlsym(RTLD_NEXT, "connect");
-		if (next_connect == NULL) {
-			errno = ENOSYS;
-			return -1;
-		}
-	}
-
-	if (getenv("NOPORT") == NULL) {
-		return next_connect(sockfd, addr, addrlen);
-	}
-
-	switch (addr->sa_family) {
-	case AF_INET:
-		port = ntohs(((struct sockaddr_in *)addr)->sin_port);
-		if (port_is_okay(port) != 0) {
-			return -1;
-		}
-		break;
-	case AF_INET6:
-		port = ntohs(((struct sockaddr_in6 *)addr)->sin6_port);
-		if (port_is_okay(port) != 0) {
-			return -1;
-		}
-		break;
-	default:
-		break;
-	}
-	return next_connect(sockfd, addr, addrlen);
-}
-
-ssize_t
-sendto(int sockfd, const void *buf, size_t len, int flags,
-       const struct sockaddr *dest_addr, socklen_t addrlen)
-{
-	unsigned short port;
-	static int (*next_sendto)(int, const void *, size_t, int,
-				  const struct sockaddr *, socklen_t);
-
-	if (next_sendto == NULL) {
-		next_sendto = dlsym(RTLD_NEXT, "sendto");
-		if (next_sendto == NULL) {
-			errno = ENOSYS;
-			return -1;
-		}
-	}
-
-	if (getenv("NOPORT") == NULL) {
-		return next_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
-	}
-
-	if (dest_addr != NULL) {
-		switch (dest_addr->sa_family) {
-		case AF_INET:
-			port = ((struct sockaddr_in *)dest_addr)->sin_port;
-			port = ntohs(port);
-			if (port_is_okay(port) != 0) {
-				return -1;
-			}
-			break;
-		case AF_INET6:
-			port = ((struct sockaddr_in6 *)dest_addr)->sin6_port;
-			port = ntohs(port);
-			if (port_is_okay(port) != 0) {
-				return -1;
-			}
-			break;
-		default:
-			break;
-		}
-	}
-	return next_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
-}
diff --git a/SPECS/krb5.spec b/SPECS/krb5.spec
index 2afc2af..afd52e3 100644
--- a/SPECS/krb5.spec
+++ b/SPECS/krb5.spec
@@ -16,9 +16,9 @@
 
 Summary: The Kerberos network authentication system
 Name: krb5
-Version: 1.16.1
+Version: 1.17
 # for prerelease, should be e.g., 0.% {prerelease}.1% { ?dist } (without spaces)
-Release: 22%{?dist}
+Release: 9%{?dist}
 
 # lookaside-cached sources; two downloads and a build artifact
 Source0: https://web.mit.edu/kerberos/dist/krb5/1.16/krb5-%{version}%{prerelease}.tar.gz
@@ -46,11 +46,8 @@ Source33: krb5kdc.logrotate
 Source34: kadmind.logrotate
 Source39: krb5-krb5kdc.conf
 
-# Carry this locally until it's available in a packaged form.
-Source100: noport.c
-
 Patch26: krb5-1.12.1-pam.patch
-Patch27: krb5-1.15.1-selinux-label.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
@@ -60,60 +57,38 @@ 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
-Patch40: Fix-hex-conversion-of-PKINIT-certid-strings.patch
-Patch41: Exit-with-status-0-from-kadmind.patch
-Patch42: Include-etype-info-in-for-hardware-preauth-hints.patch
-Patch43: Fix-securid_sam2-preauth-for-non-default-salt.patch
-Patch44: Refactor-KDC-krb5_pa_data-utility-functions.patch
-Patch45: Simplify-kdc_preauth.c-systems-table.patch
-Patch46: Add-PKINIT-client-support-for-freshness-token.patch
-Patch47: Add-PKINIT-KDC-support-for-freshness-token.patch
-Patch49: Fix-read-overflow-in-KDC-sort_pa_data.patch
-Patch50: Include-preauth-name-in-trace-output-if-possible.patch
-Patch51: Report-extended-errors-in-kinit-k-t-KDB.patch
-Patch52: Add-libkrb5support-hex-functions-and-tests.patch
-Patch53: Use-libkrb5support-hex-functions-where-appropriate.patch
-Patch54: Add-ASN.1-encoders-and-decoders-for-SPAKE-types.patch
-Patch55: Add-k5_buf_add_vfmt-to-k5buf-interface.patch
-Patch56: Add-vector-support-to-k5_sha256.patch
-Patch57: Move-zap-definition-to-k5-platform.h.patch
-Patch58: Implement-k5_buf_init_dynamic_zap.patch
-Patch59: Use-k5_buf_init_dynamic_zap-where-appropriate.patch
-Patch60: Add-SPAKE-preauth-support.patch
-Patch61: Add-doc-index-entries-for-SPAKE-constants.patch
-Patch62: Fix-SPAKE-memory-leak.patch
-Patch64: Zap-data-when-freeing-krb5_spake_factor.patch
-Patch65: Be-more-careful-asking-for-AS-key-in-SPAKE-client.patch
-Patch68: Restrict-pre-authentication-fallback-cases.patch
-Patch69: Remove-nodes-option-from-make-certs-scripts.patch
-Patch70: Fix-segfault-in-finish_dispatch.patch
-Patch71: Log-when-non-root-ksu-authorization-fails.patch
-Patch72: Add-k5_dir_filenames-to-libkrb5support.patch
-Patch73: Process-profile-includedir-in-sorted-order.patch
-Patch74: Make-docs-build-python3-compatible.patch
-Patch75: Add-flag-to-disable-encrypted-timestamp-on-client.patch
-Patch76: Explicitly-look-for-python2-in-configure.in.patch
-Patch77: Use-SHA-256-instead-of-MD5-for-audit-ticket-IDs.patch
-Patch78: Add-k5test-mark-function.patch
-Patch79: Convert-Python-tests-to-Python-3.patch
-Patch80: Zap-copy-of-secret-in-RC4-string-to-key.patch
-Patch81: Fix-some-broken-tests-for-Python-3.patch
-Patch82: Eliminate-preprocessor-disabled-dead-code.patch
-Patch83: Make-krb5kdc-p-affect-TCP-ports.patch
-Patch84: Remove-outdated-note-in-krb5kdc-man-page.patch
-Patch85: Fix-k5test-prompts-for-Python-3.patch
-Patch86: Become-FIPS-aware.patch
 Patch87: In-FIPS-mode-add-plaintext-fallback-for-RC4-usages-a.patch
-Patch88: Remove-incorrect-KDC-assertion.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
+Patch92: Use-openssl-s-PRNG-in-FIPS-mode.patch
+Patch93: Become-FIPS-aware-with-3DES.patch
+Patch94: FIPS-aware-SPAKE-group-negotiation.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
 
 License: MIT
 URL: http://web.mit.edu/kerberos/www/
 Group: System Environment/Libraries
+
 BuildRequires: autoconf, bison, cmake, flex, gawk, gettext, pkgconfig, sed
 BuildRequires: gcc
 BuildRequires: libcom_err-devel, libedit-devel, libss-devel
 BuildRequires: gzip, ncurses-devel
 BuildRequires: python3-sphinx, texlive-pdftex, latexmk
+BuildRequires: libverto-devel
+BuildRequires: openldap-devel
+BuildRequires: openssl-devel >= 0.9.8
+BuildRequires: python3
+BuildRequires: keyutils, keyutils-libs-devel >= 1.5.8
+BuildRequires: libselinux-devel
+BuildRequires: pam-devel
+BuildRequires: tcl-devel
 
 # For autosetup
 BuildRequires: git
@@ -144,27 +119,12 @@ BuildRequires: tex(wrapfig.sty)
 # Typical fonts, and the commands which we need to have present.
 BuildRequires: texlive, texlive-latex, texlive-texmf-fonts
 BuildRequires: /usr/bin/pdflatex /usr/bin/makeindex
-BuildRequires: keyutils, keyutils-libs-devel >= 1.5.8
-BuildRequires: libselinux-devel
-BuildRequires: pam-devel
 BuildRequires: systemd-units
 
-# For the test framework.
-BuildRequires: perl-interpreter, dejagnu, tcl-devel, python3
-BuildRequires: net-tools, rpcbind
-BuildRequires: hostname
-BuildRequires: iproute
-BuildRequires: libverto-devel
-BuildRequires: openldap-devel
-BuildRequires: openssl-devel >= 0.9.8
-
 %ifarch %{ix86} x86_64
 BuildRequires: yasm
 %endif
 
-BuildRequires: nss_wrapper
-BuildRequires: socket_wrapper
-
 %description
 Kerberos V5 is a trusted-third-party network authentication system,
 which can improve your network's security by eliminating the insecure
@@ -178,7 +138,9 @@ Requires: libkadm5%{?_isa} = %{version}-%{release}
 Requires: libcom_err-devel
 Requires: keyutils-libs-devel, libselinux-devel
 Requires: libverto-devel
-Provides: krb5-kdb-version = %{kdbversion}
+Provides: krb5-kdb-devel-version = %{kdbversion}
+# IPA wants ^ to be a separate symbol because they don't trust package
+# managers to match -server and -devel in version.  Just go with it.
 
 %description devel
 Kerberos is a network authentication system. The krb5-devel package
@@ -222,6 +184,7 @@ Obsoletes: %{name}-server-%{version}-%{release}.ppc
 Obsoletes: %{name}-server-%{version}-%{release}.s390
 %endif
 Requires: libkadm5%{?_isa} = %{version}-%{release}
+Provides: krb5-kdb-version = %{kdbversion}
 
 %description server
 Kerberos is a network authentication system. The krb5-server package
@@ -397,45 +360,6 @@ done
 # new krb5-%{version}-pdf
 tar -cf "krb5-%{version}%{prerelease}-pdfs.tar.new" build-pdf/*.pdf
 
-# We need to cut off any access to locally-running nameservers, too.
-%{__cc} -fPIC -shared -o noport.so -Wall -Wextra $RPM_SOURCE_DIR/noport.c
-
-%check
-%ifarch i686
-# i686 isn't an installable arch - it's only for multilib.  So don't
-# bother testing the client or server code.  (Library code is already
-# not testable in brew/koji/copr.)
-exit 0
-%endif
-
-mkdir nss_wrapper
-
-# Set things up to use the test wrappers.
-export NSS_WRAPPER_HOSTNAME=test.example.com
-export NSS_WRAPPER_HOSTS="$PWD/nss_wrapper/fakehosts"
-echo "127.0.0.1 $NSS_WRAPPER_HOSTNAME localhost" > $NSS_WRAPPER_HOSTS
-export NOPORT='53,111'
-export SOCKET_WRAPPER_DIR="$PWD/sockets" ; mkdir -p $SOCKET_WRAPPER_DIR
-export LD_PRELOAD="$PWD/noport.so:libnss_wrapper.so:libsocket_wrapper.so"
-
-# ugh.  COPR doesn't expose the keyring, so try to cope.
-%if 0%{?copr_username:1}
-%global keyctl :
-%else
-%global keyctl keyctl
-%endif
-
-# Run the test suite. We can't actually run the whole thing in the build
-# system, but we can at least run more than we used to.  The build system may
-# give us a revoked session keyring, so run affected tests with a new one.
-make -C src runenv.py
-: make -C src check TMPDIR=%{_tmppath}
-%{keyctl} session - make -C src/lib check TMPDIR=%{_tmppath} OFFLINE=yes
-make -C src/kdc check TMPDIR=%{_tmppath}
-%{keyctl} session - make -C src/appl check TMPDIR=%{_tmppath}
-make -C src/clients check TMPDIR=%{_tmppath}
-%{keyctl} session - make -C src/util check TMPDIR=%{_tmppath}
-
 %install
 [ "$RPM_BUILD_ROOT" != '/' ] && rm -rf -- "$RPM_BUILD_ROOT"
 
@@ -700,6 +624,7 @@ exit 0
 /%{_mandir}/man5/k5identity.5*
 /%{_mandir}/man5/k5login.5*
 /%{_mandir}/man5/krb5.conf.5*
+/%{_mandir}/man7/kerberos.7*
 %{_libdir}/libgssapi_krb5.so.*
 %{_libdir}/libgssrpc.so.*
 %{_libdir}/libk5crypto.so.*
@@ -758,6 +683,42 @@ exit 0
 %{_libdir}/libkadm5srv_mit.so.*
 
 %changelog
+* Tue Sep 17 2019 Robbie Harwood <rharwood@redhat.com> - 1.17-9
+- Fix argument order on strlcpy() in enctype_name()
+- Resolves: #1754369
+
+* Wed Aug 07 2019 Robbie Harwood <rharwood@redhat.com> - 1.17-8
+- Clean up etype display on KDC
+- Resolves: #1664157
+
+* Tue Jun 04 2019 Robbie Harwood <rharwood@redhat.com> - 1.17-7
+- Fix pkinit_anchors path
+- Resolves: #1661339
+
+* Wed May 15 2019 Robbie Harwood <rharwood@redhat.com> - 1.17-6
+- Re-provide krb5-kdb-version in -devel as well (IPA wants it)
+- Resolves: #1645594
+
+* Thu Apr 18 2019 Robbie Harwood <rharwood@redhat.com> - 1.17-5
+- Move kdbversion info into -server for IPA (so we can rebase)
+- Resolves: #1645594
+
+* Mon Apr 01 2019 Robbie Harwood <rharwood@redhat.com> - 1.17-4
+- FIPS: disable 3DES and ed25519
+- Resolves: #1616326
+
+* Tue Mar 19 2019 Robbie Harwood <rharwood@redhat.com> - 1.17-3
+- Use openssl's PRNG in FIPS mode
+- Resolves: #1663571
+
+* Tue Mar 19 2019 Robbie Harwood <rharwood@redhat.com> - 1.17-2
+- Address some optimized-out memset() calls
+- Resolves: #1663503
+
+* Mon Mar 18 2019 Robbie Harwood <rharwood@redhat.com> - 1.17-1
+- New upstream version (1.17)
+- Resolves: #1645594
+
 * Thu Feb 07 2019 Robbie Harwood <rharwood@redhat.com> - 1.16.1-22
 - Remove incorrect KDC assertion
 - Resolves: #1673016