From 2c340efca2219c5c003b6f2c87c7d314d7a70d05 Mon Sep 17 00:00:00 2001 From: Robbie Harwood Date: Tue, 27 Mar 2018 11:02:50 -0400 Subject: [PATCH] Add SPAKE support - Improve protections on internal sensitive buffers - Improve internal hex encoding/decoding --- ...ncoders-and-decoders-for-SPAKE-types.patch | 866 + Add-SPAKE-preauth-support.patch | 14349 ++++++++++++++++ ...oc-index-entries-for-SPAKE-constants.patch | 31 + Add-k5_buf_add_vfmt-to-k5buf-interface.patch | 119 + ...bkrb5support-hex-functions-and-tests.patch | 496 + Add-vector-support-to-k5_sha256.patch | 106 + Implement-k5_buf_init_dynamic_zap.patch | 149 + Move-zap-definition-to-k5-platform.h.patch | 151 + ...f_init_dynamic_zap-where-appropriate.patch | 62 + ...port-hex-functions-where-appropriate.patch | 869 + kdc.conf | 19 +- krb5.conf | 1 + krb5.spec | 19 +- 13 files changed, 17226 insertions(+), 11 deletions(-) create mode 100644 Add-ASN.1-encoders-and-decoders-for-SPAKE-types.patch create mode 100644 Add-SPAKE-preauth-support.patch create mode 100644 Add-doc-index-entries-for-SPAKE-constants.patch create mode 100644 Add-k5_buf_add_vfmt-to-k5buf-interface.patch create mode 100644 Add-libkrb5support-hex-functions-and-tests.patch create mode 100644 Add-vector-support-to-k5_sha256.patch create mode 100644 Implement-k5_buf_init_dynamic_zap.patch create mode 100644 Move-zap-definition-to-k5-platform.h.patch create mode 100644 Use-k5_buf_init_dynamic_zap-where-appropriate.patch create mode 100644 Use-libkrb5support-hex-functions-where-appropriate.patch diff --git a/Add-ASN.1-encoders-and-decoders-for-SPAKE-types.patch b/Add-ASN.1-encoders-and-decoders-for-SPAKE-types.patch new file mode 100644 index 0000000..96377e8 --- /dev/null +++ b/Add-ASN.1-encoders-and-decoders-for-SPAKE-types.patch @@ -0,0 +1,866 @@ +From 09304f3859f2dd637b7cc27ba1cb3fb3603a3576 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +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 ++#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 + + 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 + #include + #include ++#include ++#include + + 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/Add-SPAKE-preauth-support.patch b/Add-SPAKE-preauth-support.patch new file mode 100644 index 0000000..e23d35c --- /dev/null +++ b/Add-SPAKE-preauth-support.patch @@ -0,0 +1,14349 @@ +From 0284b6503c003af90b9c317620d38b488dadcf86 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +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 ++++++++ + src/plugins/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 1db2420a7..9dc1148b1 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 4ed9832c7..8cfe5f458 100644 +--- a/doc/admin/conf_files/krb5_conf.rst ++++ b/doc/admin/conf_files/krb5_conf.rst +@@ -365,6 +365,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 `, 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 26011550b..cacfd659a 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 ++# Individual's name ++# See CONTRIBUTORS for the meaning of multiple email addresses. ++ ++# Please keep the list sorted. ++ ++Andres Erbsen ++Google Inc. ++Jade Philipoom ++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 ++#include ++ ++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 ++#include ++#include ++#include ++ ++/* 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 ++ ++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 ++ ++/* ++ * 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 ++ ++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/Add-doc-index-entries-for-SPAKE-constants.patch b/Add-doc-index-entries-for-SPAKE-constants.patch new file mode 100644 index 0000000..3bf7e4e --- /dev/null +++ b/Add-doc-index-entries-for-SPAKE-constants.patch @@ -0,0 +1,31 @@ +From c4c9ca6edde2157cd42839d227e5f3defd4011a1 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +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/Add-k5_buf_add_vfmt-to-k5buf-interface.patch b/Add-k5_buf_add_vfmt-to-k5buf-interface.patch new file mode 100644 index 0000000..0510e92 --- /dev/null +++ b/Add-k5_buf_add_vfmt-to-k5buf-interface.patch @@ -0,0 +1,119 @@ +From 4705fc3c9df924b0c1de015e63f95f98eb563dd3 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +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/Add-libkrb5support-hex-functions-and-tests.patch b/Add-libkrb5support-hex-functions-and-tests.patch new file mode 100644 index 0000000..b09b708 --- /dev/null +++ b/Add-libkrb5support-hex-functions-and-tests.patch @@ -0,0 +1,496 @@ +From 9fa4d4095164c09b70061fce5c31ccbd97bc7553 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Mon, 19 Feb 2018 00:51:44 -0500 +Subject: [PATCH] Add libkrb5support hex functions and tests + +(cherry picked from commit 720dea558da0062d3cea4385327161e62cf09a5e) +--- + .gitignore | 1 + + 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 ++++++++++++++++++++++++++ + 7 files changed, 359 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/.gitignore b/.gitignore +index c13b5e356..91c8b942e 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -517,6 +517,7 @@ local.properties + + /src/util/support/libkrb5support.exports + /src/util/support/t_base64 ++/src/util/support/t_hex + /src/util/support/t_json + /src/util/support/t_k5buf + /src/util/support/t_path +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 ++#include ++#include ++ ++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 ++#include ++ ++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/Add-vector-support-to-k5_sha256.patch b/Add-vector-support-to-k5_sha256.patch new file mode 100644 index 0000000..1a04ac4 --- /dev/null +++ b/Add-vector-support-to-k5_sha256.patch @@ -0,0 +1,106 @@ +From 73fe8ea67105a4e056c82a0593dad8e6820f05d4 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +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 + + 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/Implement-k5_buf_init_dynamic_zap.patch b/Implement-k5_buf_init_dynamic_zap.patch new file mode 100644 index 0000000..4f78d34 --- /dev/null +++ b/Implement-k5_buf_init_dynamic_zap.patch @@ -0,0 +1,149 @@ +From 7a578d56d42d12973ec17be4cffd983c57aa38c9 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +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/Move-zap-definition-to-k5-platform.h.patch b/Move-zap-definition-to-k5-platform.h.patch new file mode 100644 index 0000000..83e7e94 --- /dev/null +++ b/Move-zap-definition-to-k5-platform.h.patch @@ -0,0 +1,151 @@ +From 5824de8b471d132ed58eece98c614c56c7b0d48d Mon Sep 17 00:00:00 2001 +From: Greg Hudson +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/Use-k5_buf_init_dynamic_zap-where-appropriate.patch b/Use-k5_buf_init_dynamic_zap-where-appropriate.patch new file mode 100644 index 0000000..a0ecfd4 --- /dev/null +++ b/Use-k5_buf_init_dynamic_zap-where-appropriate.patch @@ -0,0 +1,62 @@ +From 9168f0c02a066543a8d03c60e4f05d5f4073f373 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +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/Use-libkrb5support-hex-functions-where-appropriate.patch b/Use-libkrb5support-hex-functions-where-appropriate.patch new file mode 100644 index 0000000..7af1f64 --- /dev/null +++ b/Use-libkrb5support-hex-functions-where-appropriate.patch @@ -0,0 +1,869 @@ +From a77bccb3fd953ae5800768efc0fb4a13753cb785 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +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 + #include "k5-platform.h" /* for asprintf */ ++#include "k5-hex.h" + + #include + #include +@@ -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 + #include +@@ -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 + #include + #include ++#include + #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 + #include + ++#include + #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 ++#include + #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 + #include + + /* Decode a password of the form {HEX}. */ + 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 + #include + #include +@@ -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/kdc.conf b/kdc.conf index e99219a..b2e5e9b 100644 --- a/kdc.conf +++ b/kdc.conf @@ -1,12 +1,13 @@ [kdcdefaults] - kdc_ports = 88 - kdc_tcp_ports = 88 + kdc_ports = 88 + kdc_tcp_ports = 88 + spake_preauth_kdc_challenge = edwards25519 [realms] - EXAMPLE.COM = { - #master_key_type = aes256-cts - acl_file = /var/kerberos/krb5kdc/kadm5.acl - dict_file = /usr/share/dict/words - admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab - supported_enctypes = aes256-cts:normal aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal camellia256-cts:normal camellia128-cts:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal - } +EXAMPLE.COM = { + #master_key_type = aes256-cts + acl_file = /var/kerberos/krb5kdc/kadm5.acl + dict_file = /usr/share/dict/words + admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab + supported_enctypes = aes256-cts:normal aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal camellia256-cts:normal camellia128-cts:normal +} diff --git a/krb5.conf b/krb5.conf index 0ba01ea..99b8859 100644 --- a/krb5.conf +++ b/krb5.conf @@ -14,6 +14,7 @@ includedir /etc/krb5.conf.d/ forwardable = true rdns = false pkinit_anchors = /etc/pki/tls/certs/ca-bundle.crt + spake_preauth_groups = edwards25519 # default_realm = EXAMPLE.COM [realms] diff --git a/krb5.spec b/krb5.spec index d243d85..a98b750 100644 --- a/krb5.spec +++ b/krb5.spec @@ -18,7 +18,7 @@ Summary: The Kerberos network authentication system Name: krb5 Version: 1.16 # for prerelease, should be e.g., 0.% {prerelease}.1% { ?dist } (without spaces) -Release: 14%{?dist} +Release: 15%{?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 @@ -75,6 +75,16 @@ Patch48: Allow-validation-of-PACs-with-enterprise-names.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 License: MIT URL: http://web.mit.edu/kerberos/www/ @@ -724,7 +734,12 @@ exit 0 %{_libdir}/libkadm5srv_mit.so.* %changelog -* Tue Mar 20 2018 Robbie Harwood - 1.16-13 +* Tue Mar 27 2018 Robbie Harwood - 1.16-15 +- Add SPAKE support +- Improve protections on internal sensitive buffers +- Improve internal hex encoding/decoding + +* Tue Mar 20 2018 Robbie Harwood - 1.16-14 - Fix problem with ccache_name logic in previous build * Tue Mar 20 2018 Robbie Harwood - 1.16-13