Path: blob/main/crypto/krb5/src/plugins/preauth/spake/edwards25519.c
34889 views
/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil -*- */1/* This file is adapted from the SPAKE edwards25519 code in BoringSSL. */2/*3* The MIT License (MIT)4*5* Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file).6*7* Permission is hereby granted, free of charge, to any person obtaining a copy8* of this software and associated documentation files (the "Software"), to9* deal in the Software without restriction, including without limitation the10* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or11* sell copies of the Software, and to permit persons to whom the Software is12* furnished to do so, subject to the following conditions:13*14* The above copyright notice and this permission notice shall be included in15* all copies or substantial portions of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS23* IN THE SOFTWARE.24*/25/*26* Copyright (c) 2015-2016, Google Inc.27*28* Permission to use, copy, modify, and/or distribute this software for any29* purpose with or without fee is hereby granted, provided that the above30* copyright notice and this permission notice appear in all copies.31*32* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES33* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF34* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY35* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES36* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION37* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN38* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.39*/4041/*42* This code is adapted from the BoringSSL edwards25519 SPAKE2 implementation43* from third_party/fiat and crypto/spake25519.c, with the following44* adaptations:45*46* - The M and N points are the ones from draft-irtf-cfrg-spake2-05. The47* BoringSSL M and N points were determined similarly, but were not48* restricted to members of the generator subgroup, so they use only one hash49* iteration for both points. The intent in BoringSSL had been to multiply w50* by the cofactor so that wM and wN would be in the subgroup, but as that51* step was accidentally omitted, a hack had to be introduced after the fact52* to add multiples of the prime order to the scalar. That hack is not53* present in this code, and the SPAKE preauth spec does not multiply w by54* the cofactor as it is unnecessary if M and N are chosen from the subgroup.55*56* - The SPAKE code is modified to fit the groups.h interface and the SPAKE57* preauth spec.58*59* - The required declarations and code are all here in one file (except for60* the generator point table, which is still in a separate header), so all of61* the functions are declared static.62*63* - BORINGSSL_CURVE25519_64BIT is defined here using autoconf tests.64*65* - curve25519_32.h and curve25519_64.h are combined into edwards25519_fiat.h66* (conditionalized on BORINGSSL_CURVE25519_64BIT) for predictable dependency67* generation. The fiat_25519_selectznz and fiat_25519_carry_scmul_12166668* functions were removed from both branches as they are not used here (the69* former because it is not used by the BoringSSL code and the latter because70* it is only used by the X25519 code). The fiat_25519_int128 and71* fiat_25519_uint128 typedefs were adjusted to work with older versions of72* gcc.73*74* - fe_cmov() has the initial "Silence an unused function warning" part75* removed, as we removed fiat_25519_selectznz instead.76*77* - The field element bounds assertion checks are disabled by default, as they78* slow the code down by roughly a factor of two. The79* OPENSSL_COMPILE_ASSERT() in fe_copy_lt() is changed to a regular assert80* and is also conditionalized. Do a build and "make check" with81* EDWARDS25519_ASSERTS defined when updating this code.82*83* - The copyright comments at the top are formatted the way we do so in other84* source files, for ease of extraction.85*86* - Declarations in for loops conflict with our compiler configuration in87* older versions of gcc, so they are moved outside of the for loop.88*89* - The preprocessor symbol OPENSSL_SMALL is changed to CONFIG_SMALL.90*91* - OPENSSL_memset and OPENSSL_memmove are changed to memset and memmove, in92* each case verifying that they are used with nonzero length arguments.93*94* - CRYPTO_memcmp is changed to k5_bcmp.95*96* - Functions used only by X25519 or Ed25519 interfaces but not SPAKE are97* removed, taking care to check for unused functions in both the 64-bit and98* 32-bit preprocessor branches. ge_p3_dbl() is unused here if CONFIG_SMALL99* is defined, so it is placed inside #ifndef CONFIG_SMALL.100*/101102// Some of this code is taken from the ref10 version of Ed25519 in SUPERCOP103// 20141124 (https://bench.cr.yp.to/supercop.html). That code is released as104// public domain but parts have been replaced with code generated by Fiat105// (https://github.com/mit-plv/fiat-crypto), which is MIT licensed.106107#include "groups.h"108#include "iana.h"109110#ifdef __GNUC__111#pragma GCC diagnostic ignored "-Wdeclaration-after-statement"112#endif113114#if SIZEOF_SIZE_T >= 8 && defined(HAVE___INT128_T) && defined(HAVE___UINT128_T)115#define BORINGSSL_CURVE25519_64BIT116typedef __int128_t int128_t;117typedef __uint128_t uint128_t;118#endif119120/* From BoringSSL crypto/curve25519/internal.h */121122#if defined(BORINGSSL_CURVE25519_64BIT)123// fe means field element. Here the field is \Z/(2^255-19). An element t,124// entries t[0]...t[4], represents the integer t[0]+2^51 t[1]+2^102 t[2]+2^153125// t[3]+2^204 t[4].126// fe limbs are bounded by 1.125*2^51.127// Multiplication and carrying produce fe from fe_loose.128typedef struct fe { uint64_t v[5]; } fe;129130// fe_loose limbs are bounded by 3.375*2^51.131// Addition and subtraction produce fe_loose from (fe, fe).132typedef struct fe_loose { uint64_t v[5]; } fe_loose;133#else134// fe means field element. Here the field is \Z/(2^255-19). An element t,135// entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77136// t[3]+2^102 t[4]+...+2^230 t[9].137// fe limbs are bounded by 1.125*2^26,1.125*2^25,1.125*2^26,1.125*2^25,etc.138// Multiplication and carrying produce fe from fe_loose.139typedef struct fe { uint32_t v[10]; } fe;140141// fe_loose limbs are bounded by 3.375*2^26,3.375*2^25,3.375*2^26,3.375*2^25,etc.142// Addition and subtraction produce fe_loose from (fe, fe).143typedef struct fe_loose { uint32_t v[10]; } fe_loose;144#endif145146// ge means group element.147//148// Here the group is the set of pairs (x,y) of field elements (see fe.h)149// satisfying -x^2 + y^2 = 1 + d x^2y^2150// where d = -121665/121666.151//152// Representations:153// ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z154// ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT155// ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T156// ge_precomp (Duif): (y+x,y-x,2dxy)157158typedef struct {159fe X;160fe Y;161fe Z;162} ge_p2;163164typedef struct {165fe X;166fe Y;167fe Z;168fe T;169} ge_p3;170171typedef struct {172fe_loose X;173fe_loose Y;174fe_loose Z;175fe_loose T;176} ge_p1p1;177178typedef struct {179fe_loose yplusx;180fe_loose yminusx;181fe_loose xy2d;182} ge_precomp;183184typedef struct {185fe_loose YplusX;186fe_loose YminusX;187fe_loose Z;188fe_loose T2d;189} ge_cached;190191#include "edwards25519_tables.h"192#include "edwards25519_fiat.h"193194/* From BoringSSL third-party/fiat/curve25519.c */195196static uint64_t load_3(const uint8_t *in) {197uint64_t result;198result = (uint64_t)in[0];199result |= ((uint64_t)in[1]) << 8;200result |= ((uint64_t)in[2]) << 16;201return result;202}203204static uint64_t load_4(const uint8_t *in) {205uint64_t result;206result = (uint64_t)in[0];207result |= ((uint64_t)in[1]) << 8;208result |= ((uint64_t)in[2]) << 16;209result |= ((uint64_t)in[3]) << 24;210return result;211}212213214// Field operations.215216#if defined(BORINGSSL_CURVE25519_64BIT)217218typedef uint64_t fe_limb_t;219#define FE_NUM_LIMBS 5220221// assert_fe asserts that |f| satisfies bounds:222//223// [[0x0 ~> 0x8cccccccccccc],224// [0x0 ~> 0x8cccccccccccc],225// [0x0 ~> 0x8cccccccccccc],226// [0x0 ~> 0x8cccccccccccc],227// [0x0 ~> 0x8cccccccccccc]]228//229// See comments in edwards25519_fiat.h for which functions use these bounds for230// inputs or outputs.231#define assert_fe(f) \232do { \233for (unsigned _assert_fe_i = 0; _assert_fe_i < 5; _assert_fe_i++) { \234assert(f[_assert_fe_i] <= UINT64_C(0x8cccccccccccc)); \235} \236} while (0)237238// assert_fe_loose asserts that |f| satisfies bounds:239//240// [[0x0 ~> 0x1a666666666664],241// [0x0 ~> 0x1a666666666664],242// [0x0 ~> 0x1a666666666664],243// [0x0 ~> 0x1a666666666664],244// [0x0 ~> 0x1a666666666664]]245//246// See comments in edwards25519_fiat.h for which functions use these bounds for247// inputs or outputs.248#define assert_fe_loose(f) \249do { \250for (unsigned _assert_fe_i = 0; _assert_fe_i < 5; _assert_fe_i++) { \251assert(f[_assert_fe_i] <= UINT64_C(0x1a666666666664)); \252} \253} while (0)254255#else256257typedef uint32_t fe_limb_t;258#define FE_NUM_LIMBS 10259260// assert_fe asserts that |f| satisfies bounds:261//262// [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333],263// [0x0 ~> 0x4666666], [0x0 ~> 0x2333333],264// [0x0 ~> 0x4666666], [0x0 ~> 0x2333333],265// [0x0 ~> 0x4666666], [0x0 ~> 0x2333333],266// [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]]267//268// See comments in edwards25519_fiat.h for which functions use these bounds for269// inputs or outputs.270#define assert_fe(f) \271do { \272for (unsigned _assert_fe_i = 0; _assert_fe_i < 10; _assert_fe_i++) { \273assert(f[_assert_fe_i] <= \274((_assert_fe_i & 1) ? 0x2333333u : 0x4666666u)); \275} \276} while (0)277278// assert_fe_loose asserts that |f| satisfies bounds:279//280// [[0x0 ~> 0xd333332], [0x0 ~> 0x6999999],281// [0x0 ~> 0xd333332], [0x0 ~> 0x6999999],282// [0x0 ~> 0xd333332], [0x0 ~> 0x6999999],283// [0x0 ~> 0xd333332], [0x0 ~> 0x6999999],284// [0x0 ~> 0xd333332], [0x0 ~> 0x6999999]]285//286// See comments in edwards25519_fiat.h for which functions use these bounds for287// inputs or outputs.288#define assert_fe_loose(f) \289do { \290for (unsigned _assert_fe_i = 0; _assert_fe_i < 10; _assert_fe_i++) { \291assert(f[_assert_fe_i] <= \292((_assert_fe_i & 1) ? 0x6999999u : 0xd333332u)); \293} \294} while (0)295296#endif // BORINGSSL_CURVE25519_64BIT297298#ifndef EDWARDS25519_ASSERTS299#undef assert_fe300#undef assert_fe_loose301#define assert_fe(f)302#define assert_fe_loose(f)303#endif304305static void fe_frombytes_strict(fe *h, const uint8_t s[32]) {306// |fiat_25519_from_bytes| requires the top-most bit be clear.307assert((s[31] & 0x80) == 0);308fiat_25519_from_bytes(h->v, s);309assert_fe(h->v);310}311312static void fe_frombytes(fe *h, const uint8_t s[32]) {313uint8_t s_copy[32];314memcpy(s_copy, s, 32);315s_copy[31] &= 0x7f;316fe_frombytes_strict(h, s_copy);317}318319static void fe_tobytes(uint8_t s[32], const fe *f) {320assert_fe(f->v);321fiat_25519_to_bytes(s, f->v);322}323324// h = 0325static void fe_0(fe *h) {326memset(h, 0, sizeof(fe));327}328329static void fe_loose_0(fe_loose *h) {330memset(h, 0, sizeof(fe_loose));331}332333// h = 1334static void fe_1(fe *h) {335memset(h, 0, sizeof(fe));336h->v[0] = 1;337}338339static void fe_loose_1(fe_loose *h) {340memset(h, 0, sizeof(fe_loose));341h->v[0] = 1;342}343344// h = f + g345// Can overlap h with f or g.346static void fe_add(fe_loose *h, const fe *f, const fe *g) {347assert_fe(f->v);348assert_fe(g->v);349fiat_25519_add(h->v, f->v, g->v);350assert_fe_loose(h->v);351}352353// h = f - g354// Can overlap h with f or g.355static void fe_sub(fe_loose *h, const fe *f, const fe *g) {356assert_fe(f->v);357assert_fe(g->v);358fiat_25519_sub(h->v, f->v, g->v);359assert_fe_loose(h->v);360}361362static void fe_carry(fe *h, const fe_loose* f) {363assert_fe_loose(f->v);364fiat_25519_carry(h->v, f->v);365assert_fe(h->v);366}367368static void fe_mul_impl(fe_limb_t out[FE_NUM_LIMBS],369const fe_limb_t in1[FE_NUM_LIMBS],370const fe_limb_t in2[FE_NUM_LIMBS]) {371assert_fe_loose(in1);372assert_fe_loose(in2);373fiat_25519_carry_mul(out, in1, in2);374assert_fe(out);375}376377static void fe_mul_ltt(fe_loose *h, const fe *f, const fe *g) {378fe_mul_impl(h->v, f->v, g->v);379}380381static void fe_mul_llt(fe_loose *h, const fe_loose *f, const fe *g) {382fe_mul_impl(h->v, f->v, g->v);383}384385static void fe_mul_ttt(fe *h, const fe *f, const fe *g) {386fe_mul_impl(h->v, f->v, g->v);387}388389static void fe_mul_tlt(fe *h, const fe_loose *f, const fe *g) {390fe_mul_impl(h->v, f->v, g->v);391}392393static void fe_mul_ttl(fe *h, const fe *f, const fe_loose *g) {394fe_mul_impl(h->v, f->v, g->v);395}396397static void fe_mul_tll(fe *h, const fe_loose *f, const fe_loose *g) {398fe_mul_impl(h->v, f->v, g->v);399}400401static void fe_sq_tl(fe *h, const fe_loose *f) {402assert_fe_loose(f->v);403fiat_25519_carry_square(h->v, f->v);404assert_fe(h->v);405}406407static void fe_sq_tt(fe *h, const fe *f) {408assert_fe_loose(f->v);409fiat_25519_carry_square(h->v, f->v);410assert_fe(h->v);411}412413// h = -f414static void fe_neg(fe_loose *h, const fe *f) {415assert_fe(f->v);416fiat_25519_opp(h->v, f->v);417assert_fe_loose(h->v);418}419420// Replace (f,g) with (g,g) if b == 1;421// replace (f,g) with (f,g) if b == 0.422//423// Preconditions: b in {0,1}.424static void fe_cmov(fe_loose *f, const fe_loose *g, fe_limb_t b) {425b = 0-b;426unsigned i;427for (i = 0; i < FE_NUM_LIMBS; i++) {428fe_limb_t x = f->v[i] ^ g->v[i];429x &= b;430f->v[i] ^= x;431}432}433434// h = f435static void fe_copy(fe *h, const fe *f) {436memmove(h, f, sizeof(fe));437}438439static void fe_copy_lt(fe_loose *h, const fe *f) {440#ifdef EDWARDS25519_ASSERTS441assert(sizeof(fe_loose) == sizeof(fe));442#endif443memmove(h, f, sizeof(fe));444}445#if !defined(CONFIG_SMALL)446static void fe_copy_ll(fe_loose *h, const fe_loose *f) {447memmove(h, f, sizeof(fe_loose));448}449#endif // !defined(CONFIG_SMALL)450451static void fe_loose_invert(fe *out, const fe_loose *z) {452fe t0;453fe t1;454fe t2;455fe t3;456int i;457458fe_sq_tl(&t0, z);459fe_sq_tt(&t1, &t0);460for (i = 1; i < 2; ++i) {461fe_sq_tt(&t1, &t1);462}463fe_mul_tlt(&t1, z, &t1);464fe_mul_ttt(&t0, &t0, &t1);465fe_sq_tt(&t2, &t0);466fe_mul_ttt(&t1, &t1, &t2);467fe_sq_tt(&t2, &t1);468for (i = 1; i < 5; ++i) {469fe_sq_tt(&t2, &t2);470}471fe_mul_ttt(&t1, &t2, &t1);472fe_sq_tt(&t2, &t1);473for (i = 1; i < 10; ++i) {474fe_sq_tt(&t2, &t2);475}476fe_mul_ttt(&t2, &t2, &t1);477fe_sq_tt(&t3, &t2);478for (i = 1; i < 20; ++i) {479fe_sq_tt(&t3, &t3);480}481fe_mul_ttt(&t2, &t3, &t2);482fe_sq_tt(&t2, &t2);483for (i = 1; i < 10; ++i) {484fe_sq_tt(&t2, &t2);485}486fe_mul_ttt(&t1, &t2, &t1);487fe_sq_tt(&t2, &t1);488for (i = 1; i < 50; ++i) {489fe_sq_tt(&t2, &t2);490}491fe_mul_ttt(&t2, &t2, &t1);492fe_sq_tt(&t3, &t2);493for (i = 1; i < 100; ++i) {494fe_sq_tt(&t3, &t3);495}496fe_mul_ttt(&t2, &t3, &t2);497fe_sq_tt(&t2, &t2);498for (i = 1; i < 50; ++i) {499fe_sq_tt(&t2, &t2);500}501fe_mul_ttt(&t1, &t2, &t1);502fe_sq_tt(&t1, &t1);503for (i = 1; i < 5; ++i) {504fe_sq_tt(&t1, &t1);505}506fe_mul_ttt(out, &t1, &t0);507}508509static void fe_invert(fe *out, const fe *z) {510fe_loose l;511fe_copy_lt(&l, z);512fe_loose_invert(out, &l);513}514515// return 0 if f == 0516// return 1 if f != 0517static int fe_isnonzero(const fe_loose *f) {518fe tight;519fe_carry(&tight, f);520uint8_t s[32];521fe_tobytes(s, &tight);522523static const uint8_t zero[32] = {0};524return k5_bcmp(s, zero, sizeof(zero)) != 0;525}526527// return 1 if f is in {1,3,5,...,q-2}528// return 0 if f is in {0,2,4,...,q-1}529static int fe_isnegative(const fe *f) {530uint8_t s[32];531fe_tobytes(s, f);532return s[0] & 1;533}534535static void fe_sq2_tt(fe *h, const fe *f) {536// h = f^2537fe_sq_tt(h, f);538539// h = h + h540fe_loose tmp;541fe_add(&tmp, h, h);542fe_carry(h, &tmp);543}544545static void fe_pow22523(fe *out, const fe *z) {546fe t0;547fe t1;548fe t2;549int i;550551fe_sq_tt(&t0, z);552fe_sq_tt(&t1, &t0);553for (i = 1; i < 2; ++i) {554fe_sq_tt(&t1, &t1);555}556fe_mul_ttt(&t1, z, &t1);557fe_mul_ttt(&t0, &t0, &t1);558fe_sq_tt(&t0, &t0);559fe_mul_ttt(&t0, &t1, &t0);560fe_sq_tt(&t1, &t0);561for (i = 1; i < 5; ++i) {562fe_sq_tt(&t1, &t1);563}564fe_mul_ttt(&t0, &t1, &t0);565fe_sq_tt(&t1, &t0);566for (i = 1; i < 10; ++i) {567fe_sq_tt(&t1, &t1);568}569fe_mul_ttt(&t1, &t1, &t0);570fe_sq_tt(&t2, &t1);571for (i = 1; i < 20; ++i) {572fe_sq_tt(&t2, &t2);573}574fe_mul_ttt(&t1, &t2, &t1);575fe_sq_tt(&t1, &t1);576for (i = 1; i < 10; ++i) {577fe_sq_tt(&t1, &t1);578}579fe_mul_ttt(&t0, &t1, &t0);580fe_sq_tt(&t1, &t0);581for (i = 1; i < 50; ++i) {582fe_sq_tt(&t1, &t1);583}584fe_mul_ttt(&t1, &t1, &t0);585fe_sq_tt(&t2, &t1);586for (i = 1; i < 100; ++i) {587fe_sq_tt(&t2, &t2);588}589fe_mul_ttt(&t1, &t2, &t1);590fe_sq_tt(&t1, &t1);591for (i = 1; i < 50; ++i) {592fe_sq_tt(&t1, &t1);593}594fe_mul_ttt(&t0, &t1, &t0);595fe_sq_tt(&t0, &t0);596for (i = 1; i < 2; ++i) {597fe_sq_tt(&t0, &t0);598}599fe_mul_ttt(out, &t0, z);600}601602603// Group operations.604605static void x25519_ge_tobytes(uint8_t s[32], const ge_p2 *h) {606fe recip;607fe x;608fe y;609610fe_invert(&recip, &h->Z);611fe_mul_ttt(&x, &h->X, &recip);612fe_mul_ttt(&y, &h->Y, &recip);613fe_tobytes(s, &y);614s[31] ^= fe_isnegative(&x) << 7;615}616617static int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t s[32]) {618fe u;619fe_loose v;620fe v3;621fe vxx;622fe_loose check;623624fe_frombytes(&h->Y, s);625fe_1(&h->Z);626fe_sq_tt(&v3, &h->Y);627fe_mul_ttt(&vxx, &v3, &d);628fe_sub(&v, &v3, &h->Z); // u = y^2-1629fe_carry(&u, &v);630fe_add(&v, &vxx, &h->Z); // v = dy^2+1631632fe_sq_tl(&v3, &v);633fe_mul_ttl(&v3, &v3, &v); // v3 = v^3634fe_sq_tt(&h->X, &v3);635fe_mul_ttl(&h->X, &h->X, &v);636fe_mul_ttt(&h->X, &h->X, &u); // x = uv^7637638fe_pow22523(&h->X, &h->X); // x = (uv^7)^((q-5)/8)639fe_mul_ttt(&h->X, &h->X, &v3);640fe_mul_ttt(&h->X, &h->X, &u); // x = uv^3(uv^7)^((q-5)/8)641642fe_sq_tt(&vxx, &h->X);643fe_mul_ttl(&vxx, &vxx, &v);644fe_sub(&check, &vxx, &u);645if (fe_isnonzero(&check)) {646fe_add(&check, &vxx, &u);647if (fe_isnonzero(&check)) {648return 0;649}650fe_mul_ttt(&h->X, &h->X, &sqrtm1);651}652653if (fe_isnegative(&h->X) != (s[31] >> 7)) {654fe_loose t;655fe_neg(&t, &h->X);656fe_carry(&h->X, &t);657}658659fe_mul_ttt(&h->T, &h->X, &h->Y);660return 1;661}662663static void ge_p2_0(ge_p2 *h) {664fe_0(&h->X);665fe_1(&h->Y);666fe_1(&h->Z);667}668669static void ge_p3_0(ge_p3 *h) {670fe_0(&h->X);671fe_1(&h->Y);672fe_1(&h->Z);673fe_0(&h->T);674}675676static void ge_cached_0(ge_cached *h) {677fe_loose_1(&h->YplusX);678fe_loose_1(&h->YminusX);679fe_loose_1(&h->Z);680fe_loose_0(&h->T2d);681}682683static void ge_precomp_0(ge_precomp *h) {684fe_loose_1(&h->yplusx);685fe_loose_1(&h->yminusx);686fe_loose_0(&h->xy2d);687}688689// r = p690static void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) {691fe_copy(&r->X, &p->X);692fe_copy(&r->Y, &p->Y);693fe_copy(&r->Z, &p->Z);694}695696// r = p697static void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {698fe_add(&r->YplusX, &p->Y, &p->X);699fe_sub(&r->YminusX, &p->Y, &p->X);700fe_copy_lt(&r->Z, &p->Z);701fe_mul_ltt(&r->T2d, &p->T, &d2);702}703704// r = p705static void x25519_ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) {706fe_mul_tll(&r->X, &p->X, &p->T);707fe_mul_tll(&r->Y, &p->Y, &p->Z);708fe_mul_tll(&r->Z, &p->Z, &p->T);709}710711// r = p712static void x25519_ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) {713fe_mul_tll(&r->X, &p->X, &p->T);714fe_mul_tll(&r->Y, &p->Y, &p->Z);715fe_mul_tll(&r->Z, &p->Z, &p->T);716fe_mul_tll(&r->T, &p->X, &p->Y);717}718719// r = p720static void ge_p1p1_to_cached(ge_cached *r, const ge_p1p1 *p) {721ge_p3 t;722x25519_ge_p1p1_to_p3(&t, p);723x25519_ge_p3_to_cached(r, &t);724}725726// r = 2 * p727static void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) {728fe trX, trZ, trT;729fe t0;730731fe_sq_tt(&trX, &p->X);732fe_sq_tt(&trZ, &p->Y);733fe_sq2_tt(&trT, &p->Z);734fe_add(&r->Y, &p->X, &p->Y);735fe_sq_tl(&t0, &r->Y);736737fe_add(&r->Y, &trZ, &trX);738fe_sub(&r->Z, &trZ, &trX);739fe_carry(&trZ, &r->Y);740fe_sub(&r->X, &t0, &trZ);741fe_carry(&trZ, &r->Z);742fe_sub(&r->T, &trT, &trZ);743}744745#ifndef CONFIG_SMALL746// r = 2 * p747static void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) {748ge_p2 q;749ge_p3_to_p2(&q, p);750ge_p2_dbl(r, &q);751}752#endif753754// r = p + q755static void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {756fe trY, trZ, trT;757758fe_add(&r->X, &p->Y, &p->X);759fe_sub(&r->Y, &p->Y, &p->X);760fe_mul_tll(&trZ, &r->X, &q->yplusx);761fe_mul_tll(&trY, &r->Y, &q->yminusx);762fe_mul_tlt(&trT, &q->xy2d, &p->T);763fe_add(&r->T, &p->Z, &p->Z);764fe_sub(&r->X, &trZ, &trY);765fe_add(&r->Y, &trZ, &trY);766fe_carry(&trZ, &r->T);767fe_add(&r->Z, &trZ, &trT);768fe_sub(&r->T, &trZ, &trT);769}770771// r = p + q772static void x25519_ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {773fe trX, trY, trZ, trT;774775fe_add(&r->X, &p->Y, &p->X);776fe_sub(&r->Y, &p->Y, &p->X);777fe_mul_tll(&trZ, &r->X, &q->YplusX);778fe_mul_tll(&trY, &r->Y, &q->YminusX);779fe_mul_tlt(&trT, &q->T2d, &p->T);780fe_mul_ttl(&trX, &p->Z, &q->Z);781fe_add(&r->T, &trX, &trX);782fe_sub(&r->X, &trZ, &trY);783fe_add(&r->Y, &trZ, &trY);784fe_carry(&trZ, &r->T);785fe_add(&r->Z, &trZ, &trT);786fe_sub(&r->T, &trZ, &trT);787}788789// r = p - q790static void x25519_ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {791fe trX, trY, trZ, trT;792793fe_add(&r->X, &p->Y, &p->X);794fe_sub(&r->Y, &p->Y, &p->X);795fe_mul_tll(&trZ, &r->X, &q->YminusX);796fe_mul_tll(&trY, &r->Y, &q->YplusX);797fe_mul_tlt(&trT, &q->T2d, &p->T);798fe_mul_ttl(&trX, &p->Z, &q->Z);799fe_add(&r->T, &trX, &trX);800fe_sub(&r->X, &trZ, &trY);801fe_add(&r->Y, &trZ, &trY);802fe_carry(&trZ, &r->T);803fe_sub(&r->Z, &trZ, &trT);804fe_add(&r->T, &trZ, &trT);805}806807static uint8_t equal(signed char b, signed char c) {808uint8_t ub = b;809uint8_t uc = c;810uint8_t x = ub ^ uc; // 0: yes; 1..255: no811uint32_t y = x; // 0: yes; 1..255: no812y -= 1; // 4294967295: yes; 0..254: no813y >>= 31; // 1: yes; 0: no814return y;815}816817static void cmov(ge_precomp *t, const ge_precomp *u, uint8_t b) {818fe_cmov(&t->yplusx, &u->yplusx, b);819fe_cmov(&t->yminusx, &u->yminusx, b);820fe_cmov(&t->xy2d, &u->xy2d, b);821}822823static void x25519_ge_scalarmult_small_precomp(824ge_p3 *h, const uint8_t a[32], const uint8_t precomp_table[15 * 2 * 32]) {825// precomp_table is first expanded into matching |ge_precomp|826// elements.827ge_precomp multiples[15];828829unsigned i;830for (i = 0; i < 15; i++) {831// The precomputed table is assumed to already clear the top bit, so832// |fe_frombytes_strict| may be used directly.833const uint8_t *bytes = &precomp_table[i*(2 * 32)];834fe x, y;835fe_frombytes_strict(&x, bytes);836fe_frombytes_strict(&y, bytes + 32);837838ge_precomp *out = &multiples[i];839fe_add(&out->yplusx, &y, &x);840fe_sub(&out->yminusx, &y, &x);841fe_mul_ltt(&out->xy2d, &x, &y);842fe_mul_llt(&out->xy2d, &out->xy2d, &d2);843}844845// See the comment above |k25519SmallPrecomp| about the structure of the846// precomputed elements. This loop does 64 additions and 64 doublings to847// calculate the result.848ge_p3_0(h);849850for (i = 63; i < 64; i--) {851unsigned j;852signed char index = 0;853854for (j = 0; j < 4; j++) {855const uint8_t bit = 1 & (a[(8 * j) + (i / 8)] >> (i & 7));856index |= (bit << j);857}858859ge_precomp e;860ge_precomp_0(&e);861862for (j = 1; j < 16; j++) {863cmov(&e, &multiples[j-1], equal(index, j));864}865866ge_cached cached;867ge_p1p1 r;868x25519_ge_p3_to_cached(&cached, h);869x25519_ge_add(&r, h, &cached);870x25519_ge_p1p1_to_p3(h, &r);871872ge_madd(&r, h, &e);873x25519_ge_p1p1_to_p3(h, &r);874}875}876877#if defined(CONFIG_SMALL)878879static void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]) {880x25519_ge_scalarmult_small_precomp(h, a, k25519SmallPrecomp);881}882883#else884885static uint8_t negative(signed char b) {886uint32_t x = b;887x >>= 31; // 1: yes; 0: no888return x;889}890891static void table_select(ge_precomp *t, int pos, signed char b) {892ge_precomp minust;893uint8_t bnegative = negative(b);894uint8_t babs = b - ((uint8_t)((-bnegative) & b) << 1);895896ge_precomp_0(t);897cmov(t, &k25519Precomp[pos][0], equal(babs, 1));898cmov(t, &k25519Precomp[pos][1], equal(babs, 2));899cmov(t, &k25519Precomp[pos][2], equal(babs, 3));900cmov(t, &k25519Precomp[pos][3], equal(babs, 4));901cmov(t, &k25519Precomp[pos][4], equal(babs, 5));902cmov(t, &k25519Precomp[pos][5], equal(babs, 6));903cmov(t, &k25519Precomp[pos][6], equal(babs, 7));904cmov(t, &k25519Precomp[pos][7], equal(babs, 8));905fe_copy_ll(&minust.yplusx, &t->yminusx);906fe_copy_ll(&minust.yminusx, &t->yplusx);907908// NOTE: the input table is canonical, but types don't encode it909fe tmp;910fe_carry(&tmp, &t->xy2d);911fe_neg(&minust.xy2d, &tmp);912913cmov(t, &minust, bnegative);914}915916// h = a * B917// where a = a[0]+256*a[1]+...+256^31 a[31]918// B is the Ed25519 base point (x,4/5) with x positive.919//920// Preconditions:921// a[31] <= 127922static void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t *a) {923signed char e[64];924signed char carry;925ge_p1p1 r;926ge_p2 s;927ge_precomp t;928int i;929930for (i = 0; i < 32; ++i) {931e[2 * i + 0] = (a[i] >> 0) & 15;932e[2 * i + 1] = (a[i] >> 4) & 15;933}934// each e[i] is between 0 and 15935// e[63] is between 0 and 7936937carry = 0;938for (i = 0; i < 63; ++i) {939e[i] += carry;940carry = e[i] + 8;941carry >>= 4;942e[i] -= carry << 4;943}944e[63] += carry;945// each e[i] is between -8 and 8946947ge_p3_0(h);948for (i = 1; i < 64; i += 2) {949table_select(&t, i / 2, e[i]);950ge_madd(&r, h, &t);951x25519_ge_p1p1_to_p3(h, &r);952}953954ge_p3_dbl(&r, h);955x25519_ge_p1p1_to_p2(&s, &r);956ge_p2_dbl(&r, &s);957x25519_ge_p1p1_to_p2(&s, &r);958ge_p2_dbl(&r, &s);959x25519_ge_p1p1_to_p2(&s, &r);960ge_p2_dbl(&r, &s);961x25519_ge_p1p1_to_p3(h, &r);962963for (i = 0; i < 64; i += 2) {964table_select(&t, i / 2, e[i]);965ge_madd(&r, h, &t);966x25519_ge_p1p1_to_p3(h, &r);967}968}969970#endif971972static void cmov_cached(ge_cached *t, ge_cached *u, uint8_t b) {973fe_cmov(&t->YplusX, &u->YplusX, b);974fe_cmov(&t->YminusX, &u->YminusX, b);975fe_cmov(&t->Z, &u->Z, b);976fe_cmov(&t->T2d, &u->T2d, b);977}978979// r = scalar * A.980// where a = a[0]+256*a[1]+...+256^31 a[31].981static void x25519_ge_scalarmult(ge_p2 *r, const uint8_t *scalar,982const ge_p3 *A) {983ge_p2 Ai_p2[8];984ge_cached Ai[16];985ge_p1p1 t;986987ge_cached_0(&Ai[0]);988x25519_ge_p3_to_cached(&Ai[1], A);989ge_p3_to_p2(&Ai_p2[1], A);990991unsigned i;992for (i = 2; i < 16; i += 2) {993ge_p2_dbl(&t, &Ai_p2[i / 2]);994ge_p1p1_to_cached(&Ai[i], &t);995if (i < 8) {996x25519_ge_p1p1_to_p2(&Ai_p2[i], &t);997}998x25519_ge_add(&t, A, &Ai[i]);999ge_p1p1_to_cached(&Ai[i + 1], &t);1000if (i < 7) {1001x25519_ge_p1p1_to_p2(&Ai_p2[i + 1], &t);1002}1003}10041005ge_p2_0(r);1006ge_p3 u;10071008for (i = 0; i < 256; i += 4) {1009ge_p2_dbl(&t, r);1010x25519_ge_p1p1_to_p2(r, &t);1011ge_p2_dbl(&t, r);1012x25519_ge_p1p1_to_p2(r, &t);1013ge_p2_dbl(&t, r);1014x25519_ge_p1p1_to_p2(r, &t);1015ge_p2_dbl(&t, r);1016x25519_ge_p1p1_to_p3(&u, &t);10171018uint8_t index = scalar[31 - i/8];1019index >>= 4 - (i & 4);1020index &= 0xf;10211022unsigned j;1023ge_cached selected;1024ge_cached_0(&selected);1025for (j = 0; j < 16; j++) {1026cmov_cached(&selected, &Ai[j], equal(j, index));1027}10281029x25519_ge_add(&t, &u, &selected);1030x25519_ge_p1p1_to_p2(r, &t);1031}1032}10331034// int64_lshift21 returns |a << 21| but is defined when shifting bits into the1035// sign bit. This works around a language flaw in C.1036static inline int64_t int64_lshift21(int64_t a) {1037return (int64_t)((uint64_t)a << 21);1038}10391040// The set of scalars is \Z/l1041// where l = 2^252 + 27742317777372353535851937790883648493.10421043// Input:1044// s[0]+256*s[1]+...+256^63*s[63] = s1045//1046// Output:1047// s[0]+256*s[1]+...+256^31*s[31] = s mod l1048// where l = 2^252 + 27742317777372353535851937790883648493.1049// Overwrites s in place.1050static void x25519_sc_reduce(uint8_t s[64]) {1051int64_t s0 = 2097151 & load_3(s);1052int64_t s1 = 2097151 & (load_4(s + 2) >> 5);1053int64_t s2 = 2097151 & (load_3(s + 5) >> 2);1054int64_t s3 = 2097151 & (load_4(s + 7) >> 7);1055int64_t s4 = 2097151 & (load_4(s + 10) >> 4);1056int64_t s5 = 2097151 & (load_3(s + 13) >> 1);1057int64_t s6 = 2097151 & (load_4(s + 15) >> 6);1058int64_t s7 = 2097151 & (load_3(s + 18) >> 3);1059int64_t s8 = 2097151 & load_3(s + 21);1060int64_t s9 = 2097151 & (load_4(s + 23) >> 5);1061int64_t s10 = 2097151 & (load_3(s + 26) >> 2);1062int64_t s11 = 2097151 & (load_4(s + 28) >> 7);1063int64_t s12 = 2097151 & (load_4(s + 31) >> 4);1064int64_t s13 = 2097151 & (load_3(s + 34) >> 1);1065int64_t s14 = 2097151 & (load_4(s + 36) >> 6);1066int64_t s15 = 2097151 & (load_3(s + 39) >> 3);1067int64_t s16 = 2097151 & load_3(s + 42);1068int64_t s17 = 2097151 & (load_4(s + 44) >> 5);1069int64_t s18 = 2097151 & (load_3(s + 47) >> 2);1070int64_t s19 = 2097151 & (load_4(s + 49) >> 7);1071int64_t s20 = 2097151 & (load_4(s + 52) >> 4);1072int64_t s21 = 2097151 & (load_3(s + 55) >> 1);1073int64_t s22 = 2097151 & (load_4(s + 57) >> 6);1074int64_t s23 = (load_4(s + 60) >> 3);1075int64_t carry0;1076int64_t carry1;1077int64_t carry2;1078int64_t carry3;1079int64_t carry4;1080int64_t carry5;1081int64_t carry6;1082int64_t carry7;1083int64_t carry8;1084int64_t carry9;1085int64_t carry10;1086int64_t carry11;1087int64_t carry12;1088int64_t carry13;1089int64_t carry14;1090int64_t carry15;1091int64_t carry16;10921093s11 += s23 * 666643;1094s12 += s23 * 470296;1095s13 += s23 * 654183;1096s14 -= s23 * 997805;1097s15 += s23 * 136657;1098s16 -= s23 * 683901;1099s23 = 0;11001101s10 += s22 * 666643;1102s11 += s22 * 470296;1103s12 += s22 * 654183;1104s13 -= s22 * 997805;1105s14 += s22 * 136657;1106s15 -= s22 * 683901;1107s22 = 0;11081109s9 += s21 * 666643;1110s10 += s21 * 470296;1111s11 += s21 * 654183;1112s12 -= s21 * 997805;1113s13 += s21 * 136657;1114s14 -= s21 * 683901;1115s21 = 0;11161117s8 += s20 * 666643;1118s9 += s20 * 470296;1119s10 += s20 * 654183;1120s11 -= s20 * 997805;1121s12 += s20 * 136657;1122s13 -= s20 * 683901;1123s20 = 0;11241125s7 += s19 * 666643;1126s8 += s19 * 470296;1127s9 += s19 * 654183;1128s10 -= s19 * 997805;1129s11 += s19 * 136657;1130s12 -= s19 * 683901;1131s19 = 0;11321133s6 += s18 * 666643;1134s7 += s18 * 470296;1135s8 += s18 * 654183;1136s9 -= s18 * 997805;1137s10 += s18 * 136657;1138s11 -= s18 * 683901;1139s18 = 0;11401141carry6 = (s6 + (1 << 20)) >> 21;1142s7 += carry6;1143s6 -= int64_lshift21(carry6);1144carry8 = (s8 + (1 << 20)) >> 21;1145s9 += carry8;1146s8 -= int64_lshift21(carry8);1147carry10 = (s10 + (1 << 20)) >> 21;1148s11 += carry10;1149s10 -= int64_lshift21(carry10);1150carry12 = (s12 + (1 << 20)) >> 21;1151s13 += carry12;1152s12 -= int64_lshift21(carry12);1153carry14 = (s14 + (1 << 20)) >> 21;1154s15 += carry14;1155s14 -= int64_lshift21(carry14);1156carry16 = (s16 + (1 << 20)) >> 21;1157s17 += carry16;1158s16 -= int64_lshift21(carry16);11591160carry7 = (s7 + (1 << 20)) >> 21;1161s8 += carry7;1162s7 -= int64_lshift21(carry7);1163carry9 = (s9 + (1 << 20)) >> 21;1164s10 += carry9;1165s9 -= int64_lshift21(carry9);1166carry11 = (s11 + (1 << 20)) >> 21;1167s12 += carry11;1168s11 -= int64_lshift21(carry11);1169carry13 = (s13 + (1 << 20)) >> 21;1170s14 += carry13;1171s13 -= int64_lshift21(carry13);1172carry15 = (s15 + (1 << 20)) >> 21;1173s16 += carry15;1174s15 -= int64_lshift21(carry15);11751176s5 += s17 * 666643;1177s6 += s17 * 470296;1178s7 += s17 * 654183;1179s8 -= s17 * 997805;1180s9 += s17 * 136657;1181s10 -= s17 * 683901;1182s17 = 0;11831184s4 += s16 * 666643;1185s5 += s16 * 470296;1186s6 += s16 * 654183;1187s7 -= s16 * 997805;1188s8 += s16 * 136657;1189s9 -= s16 * 683901;1190s16 = 0;11911192s3 += s15 * 666643;1193s4 += s15 * 470296;1194s5 += s15 * 654183;1195s6 -= s15 * 997805;1196s7 += s15 * 136657;1197s8 -= s15 * 683901;1198s15 = 0;11991200s2 += s14 * 666643;1201s3 += s14 * 470296;1202s4 += s14 * 654183;1203s5 -= s14 * 997805;1204s6 += s14 * 136657;1205s7 -= s14 * 683901;1206s14 = 0;12071208s1 += s13 * 666643;1209s2 += s13 * 470296;1210s3 += s13 * 654183;1211s4 -= s13 * 997805;1212s5 += s13 * 136657;1213s6 -= s13 * 683901;1214s13 = 0;12151216s0 += s12 * 666643;1217s1 += s12 * 470296;1218s2 += s12 * 654183;1219s3 -= s12 * 997805;1220s4 += s12 * 136657;1221s5 -= s12 * 683901;1222s12 = 0;12231224carry0 = (s0 + (1 << 20)) >> 21;1225s1 += carry0;1226s0 -= int64_lshift21(carry0);1227carry2 = (s2 + (1 << 20)) >> 21;1228s3 += carry2;1229s2 -= int64_lshift21(carry2);1230carry4 = (s4 + (1 << 20)) >> 21;1231s5 += carry4;1232s4 -= int64_lshift21(carry4);1233carry6 = (s6 + (1 << 20)) >> 21;1234s7 += carry6;1235s6 -= int64_lshift21(carry6);1236carry8 = (s8 + (1 << 20)) >> 21;1237s9 += carry8;1238s8 -= int64_lshift21(carry8);1239carry10 = (s10 + (1 << 20)) >> 21;1240s11 += carry10;1241s10 -= int64_lshift21(carry10);12421243carry1 = (s1 + (1 << 20)) >> 21;1244s2 += carry1;1245s1 -= int64_lshift21(carry1);1246carry3 = (s3 + (1 << 20)) >> 21;1247s4 += carry3;1248s3 -= int64_lshift21(carry3);1249carry5 = (s5 + (1 << 20)) >> 21;1250s6 += carry5;1251s5 -= int64_lshift21(carry5);1252carry7 = (s7 + (1 << 20)) >> 21;1253s8 += carry7;1254s7 -= int64_lshift21(carry7);1255carry9 = (s9 + (1 << 20)) >> 21;1256s10 += carry9;1257s9 -= int64_lshift21(carry9);1258carry11 = (s11 + (1 << 20)) >> 21;1259s12 += carry11;1260s11 -= int64_lshift21(carry11);12611262s0 += s12 * 666643;1263s1 += s12 * 470296;1264s2 += s12 * 654183;1265s3 -= s12 * 997805;1266s4 += s12 * 136657;1267s5 -= s12 * 683901;1268s12 = 0;12691270carry0 = s0 >> 21;1271s1 += carry0;1272s0 -= int64_lshift21(carry0);1273carry1 = s1 >> 21;1274s2 += carry1;1275s1 -= int64_lshift21(carry1);1276carry2 = s2 >> 21;1277s3 += carry2;1278s2 -= int64_lshift21(carry2);1279carry3 = s3 >> 21;1280s4 += carry3;1281s3 -= int64_lshift21(carry3);1282carry4 = s4 >> 21;1283s5 += carry4;1284s4 -= int64_lshift21(carry4);1285carry5 = s5 >> 21;1286s6 += carry5;1287s5 -= int64_lshift21(carry5);1288carry6 = s6 >> 21;1289s7 += carry6;1290s6 -= int64_lshift21(carry6);1291carry7 = s7 >> 21;1292s8 += carry7;1293s7 -= int64_lshift21(carry7);1294carry8 = s8 >> 21;1295s9 += carry8;1296s8 -= int64_lshift21(carry8);1297carry9 = s9 >> 21;1298s10 += carry9;1299s9 -= int64_lshift21(carry9);1300carry10 = s10 >> 21;1301s11 += carry10;1302s10 -= int64_lshift21(carry10);1303carry11 = s11 >> 21;1304s12 += carry11;1305s11 -= int64_lshift21(carry11);13061307s0 += s12 * 666643;1308s1 += s12 * 470296;1309s2 += s12 * 654183;1310s3 -= s12 * 997805;1311s4 += s12 * 136657;1312s5 -= s12 * 683901;1313s12 = 0;13141315carry0 = s0 >> 21;1316s1 += carry0;1317s0 -= int64_lshift21(carry0);1318carry1 = s1 >> 21;1319s2 += carry1;1320s1 -= int64_lshift21(carry1);1321carry2 = s2 >> 21;1322s3 += carry2;1323s2 -= int64_lshift21(carry2);1324carry3 = s3 >> 21;1325s4 += carry3;1326s3 -= int64_lshift21(carry3);1327carry4 = s4 >> 21;1328s5 += carry4;1329s4 -= int64_lshift21(carry4);1330carry5 = s5 >> 21;1331s6 += carry5;1332s5 -= int64_lshift21(carry5);1333carry6 = s6 >> 21;1334s7 += carry6;1335s6 -= int64_lshift21(carry6);1336carry7 = s7 >> 21;1337s8 += carry7;1338s7 -= int64_lshift21(carry7);1339carry8 = s8 >> 21;1340s9 += carry8;1341s8 -= int64_lshift21(carry8);1342carry9 = s9 >> 21;1343s10 += carry9;1344s9 -= int64_lshift21(carry9);1345carry10 = s10 >> 21;1346s11 += carry10;1347s10 -= int64_lshift21(carry10);13481349s[0] = s0 >> 0;1350s[1] = s0 >> 8;1351s[2] = (s0 >> 16) | (s1 << 5);1352s[3] = s1 >> 3;1353s[4] = s1 >> 11;1354s[5] = (s1 >> 19) | (s2 << 2);1355s[6] = s2 >> 6;1356s[7] = (s2 >> 14) | (s3 << 7);1357s[8] = s3 >> 1;1358s[9] = s3 >> 9;1359s[10] = (s3 >> 17) | (s4 << 4);1360s[11] = s4 >> 4;1361s[12] = s4 >> 12;1362s[13] = (s4 >> 20) | (s5 << 1);1363s[14] = s5 >> 7;1364s[15] = (s5 >> 15) | (s6 << 6);1365s[16] = s6 >> 2;1366s[17] = s6 >> 10;1367s[18] = (s6 >> 18) | (s7 << 3);1368s[19] = s7 >> 5;1369s[20] = s7 >> 13;1370s[21] = s8 >> 0;1371s[22] = s8 >> 8;1372s[23] = (s8 >> 16) | (s9 << 5);1373s[24] = s9 >> 3;1374s[25] = s9 >> 11;1375s[26] = (s9 >> 19) | (s10 << 2);1376s[27] = s10 >> 6;1377s[28] = (s10 >> 14) | (s11 << 7);1378s[29] = s11 >> 1;1379s[30] = s11 >> 9;1380s[31] = s11 >> 17;1381}13821383/* Loosely from BoringSSL crypto/curve25519/spake25519.c */13841385/*1386* Here BoringSSL uses different points, not restricted to the generator1387* subgroup, while we use the draft-irtf-cfrg-spake2-05 points. The Python1388* code is modified to add the subgroup restriction.1389*/13901391// The following precomputation tables are for the following1392// points:1393//1394// N (found in 7 iterations):1395// x: 107422535108139575970479799629669274675752359742547651870316014610556990249311396// y: 197966860479374806510991079894277978226525291494286977460665329217055714016831397// encoded: d3bfb518f44f3430f29d0c92af503865a1ed3281dc69b35dd868ba85f886c4ab1398//1399// M (found in 21 iterations):1400// x: 81586889671492313072666666833267429152892882801913508171969117336321873853191401// y: 216223337506598786244414784677984614276170299066297246573312230682770981050401402// encoded: d048032c6ea0b6d697ddc2e86bda85a33adac920f1bf18e1b0c6d166a5cecdaf1403//1404// These points and their precomputation tables are generated with the1405// following Python code.14061407/*1408import hashlib1409import ed25519 as E # https://ed25519.cr.yp.to/python/ed25519.py14101411SEED_N = 'edwards25519 point generation seed (N)'1412SEED_M = 'edwards25519 point generation seed (M)'14131414def genpoint(seed):1415v = hashlib.sha256(seed).digest()1416it = 11417while True:1418try:1419x,y = E.decodepoint(v)1420if E.scalarmult((x,y), E.l) != [0, 1]:1421raise Exception('point has wrong order')1422except Exception, e:1423print e1424it += 11425v = hashlib.sha256(v).digest()1426continue1427print "Found in %d iterations:" % it1428print " x = %d" % x1429print " y = %d" % y1430print " Encoded (hex)"1431print E.encodepoint((x,y)).encode('hex')1432return (x,y)14331434def gentable(P):1435t = []1436for i in range(1,16):1437k = (i >> 3 & 1) * (1 << 192) + \1438(i >> 2 & 1) * (1 << 128) + \1439(i >> 1 & 1) * (1 << 64) + \1440(i & 1)1441t.append(E.scalarmult(P, k))1442return ''.join(E.encodeint(x) + E.encodeint(y) for (x,y) in t)14431444def printtable(table, name):1445print "static const uint8_t %s[15 * 2 * 32] = {" % name,1446for i in range(15 * 2 * 32):1447if i % 12 == 0:1448print "\n ",1449print " 0x%02x," % ord(table[i]),1450print "\n};"14511452if __name__ == "__main__":1453print "Searching for N"1454N = genpoint(SEED_N)1455print "Generating precomputation table for N"1456Ntable = gentable(N)1457printtable(Ntable, "kSpakeNSmallPrecomp")14581459print "Searching for M"1460M = genpoint(SEED_M)1461print "Generating precomputation table for M"1462Mtable = gentable(M)1463printtable(Mtable, "kSpakeMSmallPrecomp")1464*/14651466static const uint8_t kSpakeNSmallPrecomp[15 * 2 * 32] = {14670x23, 0xfc, 0x27, 0x6c, 0x55, 0xaf, 0xb3, 0x9c, 0xd8, 0x99, 0x3a, 0x0d,14680x7f, 0x08, 0xc9, 0xeb, 0x4d, 0x6e, 0x90, 0x99, 0x2f, 0x3c, 0x15, 0x2b,14690x89, 0x5a, 0x0f, 0xf2, 0x67, 0xe6, 0xbf, 0x17, 0xd3, 0xbf, 0xb5, 0x18,14700xf4, 0x4f, 0x34, 0x30, 0xf2, 0x9d, 0x0c, 0x92, 0xaf, 0x50, 0x38, 0x65,14710xa1, 0xed, 0x32, 0x81, 0xdc, 0x69, 0xb3, 0x5d, 0xd8, 0x68, 0xba, 0x85,14720xf8, 0x86, 0xc4, 0x2b, 0x53, 0x93, 0xb1, 0x99, 0x90, 0x30, 0xca, 0xb0,14730xbd, 0xea, 0x14, 0x4c, 0x6f, 0x2b, 0x81, 0x1e, 0x23, 0x45, 0xb2, 0x32,14740x2e, 0x2d, 0xe6, 0xb8, 0x5d, 0xc5, 0x15, 0x91, 0x63, 0x39, 0x18, 0x5b,14750x62, 0x63, 0x9b, 0xf4, 0x8b, 0xe0, 0x34, 0xa2, 0x95, 0x11, 0x92, 0x68,14760x54, 0xb7, 0xf3, 0x91, 0xca, 0x22, 0xad, 0x08, 0xd8, 0x9c, 0xa2, 0xf0,14770xdc, 0x9c, 0x2c, 0x84, 0x32, 0x26, 0xe0, 0x17, 0x89, 0x53, 0x6b, 0xfd,14780x76, 0x97, 0x25, 0xea, 0x99, 0x94, 0xf8, 0x29, 0x7c, 0xc4, 0x53, 0xc0,14790x98, 0x9a, 0x20, 0xdc, 0x70, 0x01, 0x50, 0xaa, 0x05, 0xa3, 0x40, 0x50,14800x66, 0x87, 0x30, 0x19, 0x12, 0xc3, 0xb8, 0x2d, 0x28, 0x8b, 0x7b, 0x48,14810xf7, 0x7b, 0xab, 0x45, 0x70, 0x2e, 0xbb, 0x85, 0xc1, 0x6c, 0xdd, 0x35,14820x00, 0x83, 0x20, 0x13, 0x82, 0x08, 0xaa, 0xa3, 0x03, 0x0f, 0xca, 0x27,14830x3e, 0x8b, 0x52, 0xc2, 0xd7, 0xb1, 0x8c, 0x22, 0xfe, 0x04, 0x4a, 0xf2,14840xe8, 0xac, 0xee, 0x2e, 0xd7, 0x77, 0x34, 0x49, 0xf2, 0xe9, 0xeb, 0x8c,14850xa6, 0xc8, 0xc6, 0xcd, 0x8a, 0x8f, 0x7c, 0x5d, 0x51, 0xc8, 0xfa, 0x6f,14860xb3, 0x93, 0xdb, 0x71, 0xef, 0x3e, 0x6e, 0xa7, 0x85, 0xc7, 0xd4, 0x3e,14870xa2, 0xe2, 0xc0, 0xaa, 0x17, 0xb3, 0xa4, 0x7c, 0xc2, 0x3f, 0x7c, 0x7a,14880xdd, 0x26, 0xde, 0x3e, 0xf1, 0x99, 0x06, 0xf7, 0x69, 0x1b, 0xc9, 0x20,14890x55, 0x4f, 0x86, 0x7a, 0x93, 0x89, 0x68, 0xe9, 0x2b, 0x2d, 0xbc, 0x08,14900x15, 0x5d, 0x2d, 0x0b, 0x4f, 0x1a, 0xb3, 0xd4, 0x8e, 0x77, 0x79, 0x2a,14910x25, 0xf9, 0xb6, 0x46, 0xfb, 0x87, 0x02, 0xa6, 0xe0, 0xd3, 0xba, 0x84,14920xea, 0x3e, 0x58, 0xa5, 0x7f, 0x8f, 0x8c, 0x39, 0x79, 0x28, 0xb5, 0xcf,14930xe4, 0xca, 0x63, 0xdc, 0xac, 0xed, 0x4b, 0x74, 0x1e, 0x94, 0x85, 0x8c,14940xe5, 0xf4, 0x76, 0x6f, 0x20, 0x67, 0x8b, 0xd8, 0xd6, 0x4b, 0xe7, 0x2d,14950xa0, 0xbd, 0xcc, 0x1f, 0xdf, 0x46, 0x9c, 0xa2, 0x49, 0x64, 0xdf, 0x24,14960x00, 0x11, 0x11, 0x45, 0x62, 0x5c, 0xd7, 0x8a, 0x00, 0x02, 0xf5, 0x9b,14970x4f, 0x53, 0x42, 0xc5, 0xd5, 0x55, 0x80, 0x73, 0x9a, 0x5b, 0x31, 0x5a,14980xbd, 0x3a, 0x43, 0xe9, 0x33, 0xe5, 0xaf, 0x1d, 0x92, 0x5e, 0x59, 0x37,14990xae, 0x57, 0xfa, 0x3b, 0xd2, 0x31, 0xae, 0xa6, 0xf9, 0xc9, 0xc1, 0x82,15000xa6, 0xa5, 0xed, 0x24, 0x53, 0x4b, 0x38, 0x22, 0xf2, 0x85, 0x8d, 0x13,15010xa6, 0x5e, 0xd6, 0x57, 0x17, 0xd3, 0x33, 0x38, 0x8d, 0x65, 0xd3, 0xcb,15020x1a, 0xa2, 0x3a, 0x2b, 0xbb, 0x61, 0x53, 0xd7, 0xff, 0xcd, 0x20, 0xb6,15030xbb, 0x8c, 0xab, 0x63, 0xef, 0xb8, 0x26, 0x7e, 0x81, 0x65, 0xaf, 0x90,15040xfc, 0xd2, 0xb6, 0x72, 0xdb, 0xe9, 0x23, 0x78, 0x12, 0x04, 0xc0, 0x03,15050x82, 0xa8, 0x7a, 0x0f, 0x48, 0x6f, 0x82, 0x7f, 0x81, 0xcd, 0xa7, 0x89,15060xdd, 0x86, 0xea, 0x5e, 0xa1, 0x50, 0x14, 0x34, 0x17, 0x64, 0x82, 0x0f,15070xc4, 0x40, 0x20, 0x1d, 0x8f, 0xfe, 0xfa, 0x99, 0xaf, 0x5b, 0xc1, 0x5d,15080xc8, 0x47, 0x07, 0x54, 0x4a, 0x22, 0x56, 0x57, 0xf1, 0x2c, 0x3b, 0x62,15090x7f, 0x12, 0x62, 0xaf, 0xfd, 0xf8, 0x04, 0x11, 0xa8, 0x51, 0xf0, 0x46,15100x5d, 0x79, 0x66, 0xff, 0x8a, 0x06, 0xef, 0x54, 0x64, 0x1b, 0x84, 0x3e,15110x41, 0xf3, 0xfe, 0x19, 0x51, 0xf7, 0x44, 0x9c, 0x16, 0xd3, 0x7a, 0x09,15120x59, 0xf5, 0x47, 0x45, 0xd0, 0x31, 0xef, 0x96, 0x2c, 0xc5, 0xc0, 0xd0,15130x56, 0xef, 0x3f, 0x07, 0x2b, 0xb7, 0x28, 0x49, 0xf5, 0xb1, 0x42, 0x18,15140xcf, 0x77, 0xd8, 0x2b, 0x71, 0x74, 0x80, 0xba, 0x34, 0x52, 0xce, 0x11,15150xfe, 0xc4, 0xb9, 0xeb, 0xf9, 0xc4, 0x5e, 0x1f, 0xd3, 0xde, 0x4b, 0x14,15160xe3, 0x6e, 0xe7, 0xd7, 0x83, 0x59, 0x98, 0xe8, 0x3d, 0x8e, 0xd6, 0x7d,15170xc0, 0x9a, 0x79, 0xb9, 0x83, 0xf1, 0xc1, 0x00, 0x5d, 0x16, 0x1b, 0x44,15180xe9, 0x02, 0xce, 0x99, 0x1e, 0x77, 0xef, 0xca, 0xbc, 0xf0, 0x6a, 0xb9,15190x65, 0x3f, 0x3c, 0xd9, 0xe1, 0x63, 0x0b, 0xbf, 0xaa, 0xa7, 0xe6, 0x6d,15200x6d, 0x3f, 0x44, 0x29, 0xa3, 0x8b, 0x6d, 0xc4, 0x81, 0xa9, 0xc3, 0x5a,15210x90, 0x55, 0x72, 0x61, 0x17, 0x22, 0x7f, 0x3e, 0x5f, 0xfc, 0xba, 0xb3,15220x7a, 0x99, 0x76, 0xe9, 0x20, 0xe5, 0xc5, 0xe8, 0x55, 0x56, 0x0f, 0x7a,15230x48, 0xe7, 0xbc, 0xe1, 0x13, 0xf4, 0x90, 0xef, 0x97, 0x6c, 0x02, 0x89,15240x4d, 0x22, 0x48, 0xda, 0xd3, 0x52, 0x45, 0x31, 0x26, 0xcc, 0xe8, 0x9e,15250x5d, 0xdd, 0x75, 0xe4, 0x1d, 0xbc, 0xb1, 0x08, 0x55, 0xaf, 0x54, 0x70,15260x0d, 0x0c, 0xf3, 0x50, 0xbc, 0x40, 0x83, 0xee, 0xdc, 0x6d, 0x8b, 0x40,15270x79, 0x62, 0x18, 0x37, 0xc4, 0x78, 0x02, 0x58, 0x7c, 0x78, 0xd3, 0x54,15280xed, 0x31, 0xbd, 0x7d, 0x48, 0xcf, 0xb6, 0x11, 0x27, 0x37, 0x9c, 0x86,15290xf7, 0x2e, 0x00, 0x7a, 0x48, 0x1b, 0xa6, 0x72, 0x70, 0x7b, 0x44, 0x45,15300xeb, 0x49, 0xbf, 0xbe, 0x09, 0x78, 0x66, 0x71, 0x12, 0x7f, 0x3d, 0x78,15310x51, 0x24, 0x82, 0xa2, 0xf0, 0x1e, 0x83, 0x81, 0x81, 0x45, 0x53, 0xfd,15320x5e, 0xf3, 0x03, 0x74, 0xbd, 0x23, 0x35, 0xf6, 0x10, 0xdd, 0x7c, 0x73,15330x46, 0x32, 0x09, 0x54, 0x99, 0x95, 0x91, 0x25, 0xb8, 0x32, 0x09, 0xd8,15340x2f, 0x97, 0x50, 0xa3, 0xf5, 0xd6, 0xb1, 0xed, 0x97, 0x51, 0x06, 0x42,15350x12, 0x0c, 0x69, 0x38, 0x09, 0xa0, 0xd8, 0x19, 0x70, 0xf7, 0x8f, 0x61,15360x0d, 0x56, 0x43, 0x66, 0x22, 0x8b, 0x0e, 0x0e, 0xf9, 0x81, 0x9f, 0xac,15370x6f, 0xbf, 0x7d, 0x04, 0x13, 0xf2, 0xe4, 0xeb, 0xfd, 0xbe, 0x4e, 0x56,15380xda, 0xe0, 0x22, 0x6d, 0x1b, 0x25, 0xc8, 0xa5, 0x9c, 0x05, 0x45, 0x52,15390x3c, 0x3a, 0xde, 0x6b, 0xac, 0x9b, 0xf8, 0x81, 0x97, 0x21, 0x46, 0xac,15400x7e, 0x89, 0xf8, 0x49, 0x58, 0xbb, 0x45, 0xac, 0xa2, 0xc4, 0x90, 0x1f,15410xb2, 0xb4, 0xf8, 0xe0, 0xcd, 0xa1, 0x9d, 0x1c, 0xf2, 0xf1, 0xdf, 0xfb,15420x88, 0x4e, 0xe5, 0x41, 0xd8, 0x6e, 0xac, 0x07, 0x87, 0x95, 0x35, 0xa6,15430x12, 0x08, 0x5d, 0x57, 0x5e, 0xaf, 0x71, 0x0f, 0x07, 0x4e, 0x81, 0x77,15440xf1, 0xef, 0xb5, 0x35, 0x5c, 0xfa, 0xf4, 0x4e, 0x42, 0xdc, 0x19, 0xfe,15450xe4, 0xd2, 0xb4, 0x27, 0xfb, 0x34, 0x1f, 0xb2, 0x6f, 0xf2, 0x95, 0xcc,15460xd4, 0x47, 0x63, 0xdc, 0x7e, 0x4f, 0x97, 0x2b, 0x7a, 0xe0, 0x80, 0x31,1547};15481549static const uint8_t kSpakeMSmallPrecomp[15 * 2 * 32] = {15500xe7, 0x45, 0x7e, 0x47, 0x49, 0x69, 0xbd, 0x1b, 0x35, 0x1c, 0x2c, 0x98,15510x03, 0xf3, 0xb3, 0x37, 0xde, 0x39, 0xa5, 0xda, 0xc0, 0x2e, 0xa4, 0xac,15520x7d, 0x08, 0x26, 0xfc, 0x80, 0xa7, 0x09, 0x12, 0xd0, 0x48, 0x03, 0x2c,15530x6e, 0xa0, 0xb6, 0xd6, 0x97, 0xdd, 0xc2, 0xe8, 0x6b, 0xda, 0x85, 0xa3,15540x3a, 0xda, 0xc9, 0x20, 0xf1, 0xbf, 0x18, 0xe1, 0xb0, 0xc6, 0xd1, 0x66,15550xa5, 0xce, 0xcd, 0x2f, 0x80, 0xa8, 0x4e, 0xc3, 0x81, 0xae, 0x68, 0x3b,15560x0d, 0xdb, 0x56, 0x32, 0x2f, 0xa8, 0x97, 0xa0, 0x5c, 0x15, 0xc1, 0xcb,15570x6f, 0x7a, 0x5f, 0xc5, 0x32, 0xfb, 0x49, 0x17, 0x18, 0xfa, 0x85, 0x08,15580x85, 0xf1, 0xe3, 0x11, 0x8e, 0x3d, 0x70, 0x20, 0x38, 0x4e, 0x0c, 0x17,15590xa1, 0xa8, 0x20, 0xd2, 0xb1, 0x1d, 0x05, 0x8d, 0x0f, 0xc9, 0x96, 0x18,15600x9d, 0x8c, 0x89, 0x8f, 0x46, 0x6a, 0x6c, 0x6e, 0x72, 0x03, 0xb2, 0x75,15610x87, 0xd8, 0xa9, 0x60, 0x93, 0x2b, 0x8b, 0x66, 0xee, 0xaf, 0xce, 0x98,15620xcd, 0x6b, 0x7c, 0x6a, 0xbe, 0x19, 0xda, 0x66, 0x7c, 0xda, 0x53, 0xa0,15630xe3, 0x9a, 0x0e, 0x53, 0x3a, 0x7c, 0x73, 0x4a, 0x37, 0xa6, 0x53, 0x23,15640x67, 0x31, 0xce, 0x8a, 0xab, 0xee, 0x72, 0x76, 0xc2, 0xb5, 0x54, 0x42,15650xcf, 0x4b, 0xc7, 0x53, 0x24, 0x59, 0xaf, 0x76, 0x53, 0x10, 0x7e, 0x25,15660x94, 0x5c, 0x23, 0xa6, 0x5e, 0x05, 0xea, 0x14, 0xad, 0x2b, 0xce, 0x50,15670x77, 0xb3, 0x7a, 0x88, 0x4c, 0xf7, 0x74, 0x04, 0x35, 0xa4, 0x0c, 0x9e,15680xee, 0x6a, 0x4c, 0x3c, 0xc1, 0x6a, 0x35, 0x4d, 0x6d, 0x8f, 0x94, 0x95,15690xe4, 0x10, 0xca, 0x46, 0x4e, 0xfa, 0x38, 0x40, 0xeb, 0x1a, 0x1b, 0x5a,15700xff, 0x73, 0x4d, 0xe9, 0xf2, 0xbe, 0x89, 0xf5, 0xd1, 0x72, 0xd0, 0x1a,15710x7b, 0x82, 0x08, 0x19, 0xda, 0x54, 0x44, 0xa5, 0x3d, 0xd8, 0x10, 0x1c,15720xcf, 0x3b, 0xc7, 0x54, 0xd5, 0x11, 0xd7, 0x2a, 0x69, 0x3f, 0xa6, 0x58,15730x74, 0xfd, 0x90, 0xb2, 0xf4, 0xc2, 0x0e, 0xf3, 0x19, 0x8f, 0x51, 0x7c,15740x31, 0x12, 0x79, 0x61, 0x16, 0xb4, 0x2f, 0x2f, 0xd0, 0x88, 0x97, 0xf2,15750xc3, 0x8c, 0xa6, 0xa3, 0x29, 0xff, 0x7e, 0x12, 0x46, 0x2a, 0x9c, 0x09,15760x7c, 0x5f, 0x87, 0x07, 0x6b, 0xa1, 0x9a, 0x57, 0x55, 0x8e, 0xb0, 0x56,15770x5d, 0xc9, 0x4c, 0x5b, 0xae, 0xd3, 0xd0, 0x8e, 0xb8, 0xac, 0xba, 0xe8,15780x54, 0x45, 0x30, 0x14, 0xf6, 0x59, 0x20, 0xc4, 0x03, 0xb7, 0x7a, 0x5d,15790x6b, 0x5a, 0xcb, 0x28, 0x60, 0xf8, 0xef, 0x61, 0x60, 0x78, 0x6b, 0xf5,15800x21, 0x4b, 0x75, 0xc2, 0x77, 0xba, 0x0e, 0x38, 0x98, 0xe0, 0xfb, 0xb7,15810x5f, 0x75, 0x87, 0x04, 0x0c, 0xb4, 0x5c, 0x09, 0x04, 0x00, 0x38, 0x4e,15820x4f, 0x7b, 0x73, 0xe5, 0xdb, 0xdb, 0xf1, 0xf4, 0x5c, 0x64, 0x68, 0xfd,15830xb1, 0x86, 0xe8, 0x89, 0xbe, 0x9c, 0xd4, 0x96, 0x1d, 0xcb, 0xdc, 0x5c,15840xef, 0xd4, 0x33, 0x28, 0xb9, 0xb6, 0xaf, 0x3b, 0xcf, 0x8d, 0x30, 0xba,15850xe8, 0x08, 0xcf, 0x84, 0xba, 0x61, 0x10, 0x9b, 0x62, 0xf6, 0x18, 0x79,15860x66, 0x87, 0x82, 0x7c, 0xaa, 0x71, 0xac, 0xd0, 0xd0, 0x32, 0xb0, 0x54,15870x03, 0xa4, 0xad, 0x3f, 0x72, 0xca, 0x22, 0xff, 0x01, 0x87, 0x08, 0x36,15880x61, 0x22, 0xaa, 0x18, 0xab, 0x3a, 0xbc, 0xf2, 0x78, 0x05, 0xe1, 0x99,15890xa3, 0x59, 0x98, 0xcc, 0x21, 0xc6, 0x2b, 0x51, 0x6d, 0x43, 0x0a, 0x46,15900x50, 0xae, 0x11, 0x7e, 0xd5, 0x23, 0x56, 0xef, 0x83, 0xc8, 0xbf, 0x42,15910xf0, 0x45, 0x52, 0x1f, 0x34, 0xbc, 0x2f, 0xb0, 0xf0, 0xce, 0xf0, 0xec,15920xd0, 0x99, 0x59, 0x2e, 0x1f, 0xab, 0xa8, 0x1e, 0x4b, 0xce, 0x1b, 0x9a,15930x75, 0xc6, 0xc4, 0x71, 0x86, 0xf0, 0x8d, 0xec, 0xb0, 0x30, 0xb9, 0x62,15940xb3, 0xb7, 0xdd, 0x96, 0x29, 0xc8, 0xbf, 0xe9, 0xb0, 0x74, 0x78, 0x7b,15950xf7, 0xea, 0xa3, 0x14, 0x12, 0x56, 0xe0, 0xf3, 0x35, 0x7a, 0x26, 0x4a,15960x4c, 0xe6, 0xdf, 0x13, 0xb5, 0x52, 0xb0, 0x2a, 0x5f, 0x2e, 0xac, 0x34,15970xab, 0x5f, 0x1a, 0x01, 0xe4, 0x15, 0x1a, 0xd1, 0xbf, 0xc9, 0x95, 0x0a,15980xac, 0x1d, 0xe7, 0x53, 0x59, 0x8d, 0xc3, 0x21, 0x78, 0x5e, 0x12, 0x97,15990x8f, 0x4e, 0x1d, 0xf9, 0xe5, 0xe2, 0xc2, 0xc4, 0xba, 0xfb, 0x50, 0x96,16000x5b, 0x43, 0xe8, 0xf7, 0x0d, 0x1b, 0x64, 0x58, 0xbe, 0xd3, 0x95, 0x7f,16010x8e, 0xf1, 0x85, 0x35, 0xba, 0x25, 0x55, 0x2e, 0x02, 0x46, 0x5c, 0xad,16020x1f, 0xc5, 0x03, 0xcc, 0xd0, 0x43, 0x4c, 0xf2, 0x5e, 0x64, 0x0a, 0x89,16030xd9, 0xfd, 0x23, 0x7d, 0x4f, 0xbe, 0x2f, 0x0f, 0x1e, 0x12, 0x4a, 0xd9,16040xf8, 0x82, 0xde, 0x8f, 0x4f, 0x98, 0xb9, 0x90, 0xf6, 0xfa, 0xd1, 0x11,16050xa6, 0xdc, 0x7e, 0x32, 0x48, 0x6a, 0x8a, 0x14, 0x5e, 0x73, 0xb9, 0x6c,16060x0e, 0xc2, 0xf9, 0xcc, 0xf0, 0x32, 0xc8, 0xb5, 0x56, 0xaa, 0x5d, 0xd2,16070x07, 0xf1, 0x6f, 0x33, 0x6f, 0x05, 0x70, 0x49, 0x60, 0x49, 0x23, 0x23,16080x14, 0x0e, 0x4c, 0x58, 0x92, 0xad, 0xa9, 0x50, 0xb1, 0x59, 0x43, 0x96,16090x7b, 0xc1, 0x51, 0x45, 0xef, 0x0d, 0xef, 0xd1, 0xe4, 0xd0, 0xce, 0xdf,16100x6a, 0xbc, 0x1b, 0xbf, 0x7a, 0x87, 0x4e, 0x47, 0x17, 0x9c, 0x34, 0x38,16110xb0, 0x3c, 0xa1, 0x04, 0xfb, 0xe2, 0x66, 0xce, 0xb6, 0x82, 0xbb, 0xad,16120xc3, 0x8e, 0x12, 0x35, 0xbc, 0x17, 0xce, 0x01, 0x2d, 0xa3, 0xa6, 0xb9,16130xfa, 0x84, 0xc2, 0x2f, 0x5a, 0x4a, 0x8c, 0x4c, 0x11, 0x4e, 0xa8, 0x14,16140xcb, 0xb8, 0x99, 0xaa, 0x2e, 0x8c, 0xa0, 0xc9, 0x5f, 0x62, 0x2a, 0x84,16150x66, 0x60, 0x0a, 0x7e, 0xdc, 0x93, 0x17, 0x45, 0x19, 0xb3, 0x93, 0x4c,16160xdc, 0xd0, 0xd5, 0x5c, 0x25, 0xd2, 0xcd, 0x4e, 0x84, 0x4c, 0x73, 0xb3,16170x90, 0xa4, 0x22, 0x05, 0x2c, 0x7c, 0x39, 0x2b, 0x70, 0xd9, 0x61, 0x76,16180xb2, 0x03, 0x71, 0xe9, 0x0e, 0xf8, 0x57, 0x85, 0xad, 0xb1, 0x2f, 0x34,16190xa5, 0x66, 0xb0, 0x0f, 0x75, 0x94, 0x6e, 0x26, 0x79, 0x99, 0xb4, 0xe2,16200xe2, 0xa3, 0x58, 0xdd, 0xb4, 0xfb, 0x74, 0xf4, 0xa1, 0xca, 0xc3, 0x30,16210xe7, 0x86, 0xb2, 0xa2, 0x2c, 0x11, 0xc9, 0x58, 0xe3, 0xc1, 0xa6, 0x5f,16220x86, 0x6a, 0xe7, 0x75, 0xd5, 0xd8, 0x63, 0x95, 0x64, 0x59, 0xbc, 0xb8,16230xb7, 0xf5, 0x12, 0xe3, 0x03, 0xc6, 0x17, 0xea, 0x4e, 0xcb, 0xee, 0x4c,16240xae, 0x03, 0xd1, 0x33, 0xd0, 0x39, 0x36, 0x00, 0x0f, 0xf4, 0x9c, 0xbd,16250x35, 0x96, 0xfd, 0x0d, 0x26, 0xb7, 0x9e, 0xf4, 0x4b, 0x6f, 0x4b, 0xf1,16260xec, 0x11, 0x00, 0x16, 0x21, 0x1e, 0xd4, 0x43, 0x23, 0x8c, 0x4a, 0xfa,16270x9e, 0xd4, 0x2b, 0x36, 0x9a, 0x43, 0x1e, 0x58, 0x31, 0xe8, 0x1f, 0x83,16280x15, 0x20, 0x31, 0x68, 0xfe, 0x27, 0xd3, 0xd8, 0x9b, 0x43, 0x81, 0x8f,16290x57, 0x32, 0x14, 0xe6, 0x9e, 0xbf, 0xd1, 0xfb, 0xdf, 0xad, 0x7a, 0x52,1630};16311632/* left_shift_3 sets |n| to |n|*8, where |n| is represented in little-endian1633* order. */1634static void left_shift_3(uint8_t n[32]) {1635uint8_t carry = 0;1636unsigned i;16371638for (i = 0; i < 32; i++) {1639const uint8_t next_carry = n[i] >> 5;1640n[i] = (n[i] << 3) | carry;1641carry = next_carry;1642}1643}16441645static krb5_error_code1646builtin_edwards25519_keygen(krb5_context context, groupdata *gdata,1647const uint8_t *wbytes, krb5_boolean use_m,1648uint8_t *priv_out, uint8_t *pub_out)1649{1650uint8_t private[64];1651krb5_data data = make_data(private, 32);1652krb5_error_code ret;16531654/* Pick x or y uniformly from [0, p*h) divisible by h. */1655ret = krb5_c_random_make_octets(context, &data);1656if (ret)1657return ret;1658memset(private + 32, 0, 32);1659x25519_sc_reduce(private);1660left_shift_3(private);16611662/* Compute X=x*G or Y=y*G. */1663ge_p3 P;1664x25519_ge_scalarmult_base(&P, private);16651666/* Compute w mod p. */1667uint8_t wreduced[64];1668memcpy(wreduced, wbytes, 32);1669memset(wreduced + 32, 0, 32);1670x25519_sc_reduce(wreduced);16711672/* Compute the mask, w*M or w*N. */1673ge_p3 mask;1674x25519_ge_scalarmult_small_precomp(&mask, wreduced,1675use_m ? kSpakeMSmallPrecomp :1676kSpakeNSmallPrecomp);16771678/* Compute the masked point T=w*M+X or S=w*N+Y. */1679ge_cached mask_cached;1680x25519_ge_p3_to_cached(&mask_cached, &mask);1681ge_p1p1 Pmasked;1682x25519_ge_add(&Pmasked, &P, &mask_cached);16831684/* Encode T or S into pub_out. */1685ge_p2 Pmasked_proj;1686x25519_ge_p1p1_to_p2(&Pmasked_proj, &Pmasked);1687x25519_ge_tobytes(pub_out, &Pmasked_proj);16881689/* Remember the private key in priv_out. */1690memcpy(priv_out, private, 32);1691return 0;1692}16931694static krb5_error_code1695builtin_edwards25519_result(krb5_context context, groupdata *gdata,1696const uint8_t *wbytes, const uint8_t *ourpriv,1697const uint8_t *theirpub, krb5_boolean use_m,1698uint8_t *elem_out)1699{1700/*1701* Check if the point received from peer is on the curve. This does not1702* verify that it is in the generator subgroup, but since our private key is1703* a multiple of the cofactor, the shared point will be in the generator1704* subgroup even if a rogue peer sends a point which is not.1705*/1706ge_p3 Qmasked;1707if (!x25519_ge_frombytes_vartime(&Qmasked, theirpub))1708return EINVAL;17091710/* Compute w mod p. */1711uint8_t wreduced[64];1712memcpy(wreduced, wbytes, 32);1713memset(wreduced + 32, 0, 32);1714x25519_sc_reduce(wreduced);17151716/* Compute the peer's mask, w*M or w*N. */1717ge_p3 peers_mask;1718x25519_ge_scalarmult_small_precomp(&peers_mask, wreduced,1719use_m ? kSpakeMSmallPrecomp :1720kSpakeNSmallPrecomp);17211722ge_cached peers_mask_cached;1723x25519_ge_p3_to_cached(&peers_mask_cached, &peers_mask);17241725/* Compute the peer's unmasked point, T-w*M or S-w*N. */1726ge_p1p1 Qcompl;1727ge_p3 Qunmasked;1728x25519_ge_sub(&Qcompl, &Qmasked, &peers_mask_cached);1729x25519_ge_p1p1_to_p3(&Qunmasked, &Qcompl);17301731/* Multiply by our private value to compute K=x*(S-w*N) or K=y*(T-w*M). */1732ge_p2 K;1733x25519_ge_scalarmult(&K, ourpriv, &Qunmasked);17341735/* Encode K into elem_out. */1736x25519_ge_tobytes(elem_out, &K);1737return 0;1738}17391740static krb5_error_code1741builtin_sha256(krb5_context context, groupdata *gdata, const krb5_data *dlist,1742size_t ndata, uint8_t *result_out)1743{1744return k5_sha256(dlist, ndata, result_out);1745}17461747groupdef builtin_edwards25519 = {1748.reg = &spake_iana_edwards25519,1749.keygen = builtin_edwards25519_keygen,1750.result = builtin_edwards25519_result,1751.hash = builtin_sha2561752};175317541755