hcrypto: Add X25519

The X25519 implementation comes from libsodium. Explicit copyright
notices have been added to each file as well as some portability changes
(e.g. align.h).
This commit is contained in:
Luke Howard
2019-12-30 21:07:04 +11:00
committed by Nicolas Williams
parent 20f9b2be48
commit beda11a079
20 changed files with 8184 additions and 5 deletions

View File

@@ -10,6 +10,7 @@ endif
AM_CPPFLAGS += -I$(top_srcdir)/lib/hx509 \
-I$(srcdir)/libtommath -DUSE_HCRYPTO_LTM=1 \
-I$(srcdir)/x25519 \
-I$(srcdir)/..
lib_LTLIBRARIES = libhcrypto.la
@@ -55,9 +56,10 @@ hcryptoinclude_HEADERS = \
rsa.h \
sha.h \
ui.h \
undef.h
undef.h \
x25519_ref10.h
install-build-headers:: $(hcryptoinclude_HEADERS)
install-build-headers:: $(hcryptoinclude_HEADERS) $(x25519include_HEADERS)
@foo='$(hcryptoinclude_HEADERS)'; \
for f in $$foo; do \
f=`basename $$f`; \
@@ -107,6 +109,7 @@ test_rand_LDADD = $(LDADD) -lm
libhcrypto_la_SOURCES = \
$(ltmsources) \
$(x25519sources)\
aes.c \
aes.h \
bn.c \
@@ -330,6 +333,10 @@ ltmsources = \
libtommath/bn_s_mp_toom_mul.c \
libtommath/bn_s_mp_toom_sqr.c
x25519sources = \
x25519/ed25519_ref10.c \
x25519/x25519_ref10.c
$(libhcrypto_la_OBJECTS) $(test_rand_OBJECTS): hcrypto-link
libhcrypto_la_CPPFLAGS = -DBUILD_HCRYPTO_LIB $(AM_CPPFLAGS)

View File

@@ -29,7 +29,7 @@
# POSSIBILITY OF SUCH DAMAGE.
#
SUBDIRS=libtommath
SUBDIRS=libtommath x25519
RELDIR=lib\hcrypto
@@ -87,7 +87,8 @@ INCFILES= \
$(HCRYPTOINCLUDEDIR)\rsa.h \
$(HCRYPTOINCLUDEDIR)\sha.h \
$(HCRYPTOINCLUDEDIR)\ui.h \
$(HCRYPTOINCLUDEDIR)\undef.h
$(HCRYPTOINCLUDEDIR)\undef.h \
$(HCRYPTOINCLUDEDIR)\x25519_ref10.h \
mkincdir:
!if !exist($(HCRYPTOINCLUDEDIR))

View File

@@ -350,4 +350,5 @@ EXPORTS
hc_EVP_CipherFinal_ex
hc_hcrypto_validate
hc_hcrypto_scalarmult_curve25519
hc_hcrypto_scalarmult_curve25519_base

View File

@@ -334,6 +334,8 @@ HEIMDAL_CRYPTO_1.0 {
hc_EVP_CipherUpdate;
hc_EVP_CipherFinal_ex;
hc_hcrypto_validate;
hc_hcrypto_scalarmult_curve25519;
hc_hcrypto_scalarmult_curve25519_base;
local:
*;
};

View File

@@ -0,0 +1,46 @@
########################################################################
#
# Copyright (c) 2009, Secure Endpoints Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 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.
#
RELDIR=lib\hcrypto\x25519
!include ../../../windows/NTMakefile.w32
intcflags=-I$(SRC)\lib\hcrypto
libx25519_OBJs= \
$(OBJ)\ed25519_ref10.obj \
$(OBJ)\x25519_ref10.obj
$(LIBX25519): $(libx25519_OBJs)
$(LIBCON)
all:: $(LIBX25519)

View File

@@ -0,0 +1,7 @@
#ifndef CRYPTO_ALIGN
# if defined(__INTEL_COMPILER) || defined(_MSC_VER)
# define CRYPTO_ALIGN(x) __declspec(align(x))
# else
# define CRYPTO_ALIGN(x) __attribute__ ((aligned(x)))
# endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,174 @@
/*
* ISC License
*
* Copyright (c) 2013-2019
* Frank Denis <j at pureftpd dot org>
*
* 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.
*/
#ifndef ed25519_ref10_H
#define ed25519_ref10_H
#include <roken.h>
#include <stddef.h>
#include <stdint.h>
/*
fe means field element.
Here the field is \Z/(2^255-19).
*/
#ifdef HAVE_TI_MODE
typedef uint64_t fe25519[5];
#else
typedef int32_t fe25519[10];
#endif
void fe25519_invert(fe25519 out, const fe25519 z);
void fe25519_frombytes(fe25519 h, const unsigned char *s);
void fe25519_tobytes(unsigned char *s, const fe25519 h);
static inline int
sodium_is_zero(const unsigned char *n, const size_t nlen)
{
size_t i;
volatile unsigned char d = 0U;
for (i = 0U; i < nlen; i++) {
d |= n[i];
}
return 1 & ((d - 1) >> 8);
}
#ifdef HAVE_TI_MODE
# include "ed25519_ref10_fe_51.h"
#else
# include "ed25519_ref10_fe_25_5.h"
#endif
/*
ge means group element.
Here the group is the set of pairs (x,y) of field elements
satisfying -x^2 + y^2 = 1 + d x^2y^2
where d = -121665/121666.
Representations:
ge25519_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
ge25519_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
ge25519_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
ge25519_precomp (Duif): (y+x,y-x,2dxy)
*/
typedef struct {
fe25519 X;
fe25519 Y;
fe25519 Z;
} ge25519_p2;
typedef struct {
fe25519 X;
fe25519 Y;
fe25519 Z;
fe25519 T;
} ge25519_p3;
typedef struct {
fe25519 X;
fe25519 Y;
fe25519 Z;
fe25519 T;
} ge25519_p1p1;
typedef struct {
fe25519 yplusx;
fe25519 yminusx;
fe25519 xy2d;
} ge25519_precomp;
typedef struct {
fe25519 YplusX;
fe25519 YminusX;
fe25519 Z;
fe25519 T2d;
} ge25519_cached;
void ge25519_tobytes(unsigned char *s, const ge25519_p2 *h);
void ge25519_p3_tobytes(unsigned char *s, const ge25519_p3 *h);
int ge25519_frombytes(ge25519_p3 *h, const unsigned char *s);
int ge25519_frombytes_negate_vartime(ge25519_p3 *h, const unsigned char *s);
void ge25519_p3_to_cached(ge25519_cached *r, const ge25519_p3 *p);
void ge25519_p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p);
void ge25519_p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p);
void ge25519_add(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_cached *q);
void ge25519_sub(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_cached *q);
void ge25519_scalarmult_base(ge25519_p3 *h, const unsigned char *a);
void ge25519_double_scalarmult_vartime(ge25519_p2 *r, const unsigned char *a,
const ge25519_p3 *A,
const unsigned char *b);
void ge25519_scalarmult(ge25519_p3 *h, const unsigned char *a,
const ge25519_p3 *p);
int ge25519_is_canonical(const unsigned char *s);
int ge25519_is_on_curve(const ge25519_p3 *p);
int ge25519_is_on_main_subgroup(const ge25519_p3 *p);
int ge25519_has_small_order(const unsigned char s[32]);
void ge25519_from_uniform(unsigned char s[32], const unsigned char r[32]);
void ge25519_from_hash(unsigned char s[32], const unsigned char h[64]);
/*
Ristretto group
*/
int ristretto255_frombytes(ge25519_p3 *h, const unsigned char *s);
void ristretto255_p3_tobytes(unsigned char *s, const ge25519_p3 *h);
void ristretto255_from_hash(unsigned char s[32], const unsigned char h[64]);
/*
The set of scalars is \Z/l
where l = 2^252 + 27742317777372353535851937790883648493.
*/
void sc25519_invert(unsigned char recip[32], const unsigned char s[32]);
void sc25519_reduce(unsigned char s[64]);
void sc25519_mul(unsigned char s[32], const unsigned char a[32],
const unsigned char b[32]);
void sc25519_muladd(unsigned char s[32], const unsigned char a[32],
const unsigned char b[32], const unsigned char c[32]);
int sc25519_is_canonical(const unsigned char s[32]);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,539 @@
/*
* ISC License
*
* Copyright (c) 2013-2019
* Frank Denis <j at pureftpd dot org>
*
* 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.
*/
#include <roken.h>
#include <string.h>
#include "private/common.h"
#include "private/quirks.h"
#include "utils.h"
/*
h = 0
*/
static inline void
fe25519_0(fe25519 h)
{
memset(&h[0], 0, 5 * sizeof h[0]);
}
/*
h = 1
*/
static inline void
fe25519_1(fe25519 h)
{
h[0] = 1;
memset(&h[1], 0, 4 * sizeof h[0]);
}
/*
h = f + g
Can overlap h with f or g.
*/
static inline void
fe25519_add(fe25519 h, const fe25519 f, const fe25519 g)
{
uint64_t h0 = f[0] + g[0];
uint64_t h1 = f[1] + g[1];
uint64_t h2 = f[2] + g[2];
uint64_t h3 = f[3] + g[3];
uint64_t h4 = f[4] + g[4];
h[0] = h0;
h[1] = h1;
h[2] = h2;
h[3] = h3;
h[4] = h4;
}
/*
h = f - g
*/
static void
fe25519_sub(fe25519 h, const fe25519 f, const fe25519 g)
{
const uint64_t mask = 0x7ffffffffffffULL;
uint64_t h0, h1, h2, h3, h4;
h0 = g[0];
h1 = g[1];
h2 = g[2];
h3 = g[3];
h4 = g[4];
h1 += h0 >> 51;
h0 &= mask;
h2 += h1 >> 51;
h1 &= mask;
h3 += h2 >> 51;
h2 &= mask;
h4 += h3 >> 51;
h3 &= mask;
h0 += 19ULL * (h4 >> 51);
h4 &= mask;
h0 = (f[0] + 0xfffffffffffdaULL) - h0;
h1 = (f[1] + 0xffffffffffffeULL) - h1;
h2 = (f[2] + 0xffffffffffffeULL) - h2;
h3 = (f[3] + 0xffffffffffffeULL) - h3;
h4 = (f[4] + 0xffffffffffffeULL) - h4;
h[0] = h0;
h[1] = h1;
h[2] = h2;
h[3] = h3;
h[4] = h4;
}
/*
h = -f
*/
static inline void
fe25519_neg(fe25519 h, const fe25519 f)
{
fe25519 zero;
fe25519_0(zero);
fe25519_sub(h, zero, f);
}
/*
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
fe25519_cmov(fe25519 f, const fe25519 g, unsigned int b)
{
const uint64_t mask = (uint64_t) (-(int64_t) b);
uint64_t f0 = f[0];
uint64_t f1 = f[1];
uint64_t f2 = f[2];
uint64_t f3 = f[3];
uint64_t f4 = f[4];
uint64_t x0 = f0 ^ g[0];
uint64_t x1 = f1 ^ g[1];
uint64_t x2 = f2 ^ g[2];
uint64_t x3 = f3 ^ g[3];
uint64_t x4 = f4 ^ g[4];
x0 &= mask;
x1 &= mask;
x2 &= mask;
x3 &= mask;
x4 &= mask;
f[0] = f0 ^ x0;
f[1] = f1 ^ x1;
f[2] = f2 ^ x2;
f[3] = f3 ^ x3;
f[4] = f4 ^ x4;
}
/*
Replace (f,g) with (g,f) if b == 1;
replace (f,g) with (f,g) if b == 0.
Preconditions: b in {0,1}.
*/
static void
fe25519_cswap(fe25519 f, fe25519 g, unsigned int b)
{
const uint64_t mask = (uint64_t) (-(int64_t) b);
uint64_t f0 = f[0];
uint64_t f1 = f[1];
uint64_t f2 = f[2];
uint64_t f3 = f[3];
uint64_t f4 = f[4];
uint64_t g0 = g[0];
uint64_t g1 = g[1];
uint64_t g2 = g[2];
uint64_t g3 = g[3];
uint64_t g4 = g[4];
uint64_t x0 = f0 ^ g0;
uint64_t x1 = f1 ^ g1;
uint64_t x2 = f2 ^ g2;
uint64_t x3 = f3 ^ g3;
uint64_t x4 = f4 ^ g4;
x0 &= mask;
x1 &= mask;
x2 &= mask;
x3 &= mask;
x4 &= mask;
f[0] = f0 ^ x0;
f[1] = f1 ^ x1;
f[2] = f2 ^ x2;
f[3] = f3 ^ x3;
f[4] = f4 ^ x4;
g[0] = g0 ^ x0;
g[1] = g1 ^ x1;
g[2] = g2 ^ x2;
g[3] = g3 ^ x3;
g[4] = g4 ^ x4;
}
/*
h = f
*/
static inline void
fe25519_copy(fe25519 h, const fe25519 f)
{
uint64_t f0 = f[0];
uint64_t f1 = f[1];
uint64_t f2 = f[2];
uint64_t f3 = f[3];
uint64_t f4 = f[4];
h[0] = f0;
h[1] = f1;
h[2] = f2;
h[3] = f3;
h[4] = f4;
}
/*
return 1 if f is in {1,3,5,...,q-2}
return 0 if f is in {0,2,4,...,q-1}
*/
static inline int
fe25519_isnegative(const fe25519 f)
{
unsigned char s[32];
fe25519_tobytes(s, f);
return s[0] & 1;
}
/*
return 1 if f == 0
return 0 if f != 0
*/
static inline int
fe25519_iszero(const fe25519 f)
{
unsigned char s[32];
fe25519_tobytes(s, f);
return sodium_is_zero(s, 32);
}
/*
h = f * g
Can overlap h with f or g.
*/
static void
fe25519_mul(fe25519 h, const fe25519 f, const fe25519 g)
{
const uint64_t mask = 0x7ffffffffffffULL;
uint128_t r0, r1, r2, r3, r4, carry;
uint64_t f0, f1, f2, f3, f4;
uint64_t f1_19, f2_19, f3_19, f4_19;
uint64_t g0, g1, g2, g3, g4;
uint64_t r00, r01, r02, r03, r04;
f0 = f[0];
f1 = f[1];
f2 = f[2];
f3 = f[3];
f4 = f[4];
g0 = g[0];
g1 = g[1];
g2 = g[2];
g3 = g[3];
g4 = g[4];
f1_19 = 19ULL * f1;
f2_19 = 19ULL * f2;
f3_19 = 19ULL * f3;
f4_19 = 19ULL * f4;
r0 = ((uint128_t) f0 ) * ((uint128_t) g0);
r0 += ((uint128_t) f1_19) * ((uint128_t) g4);
r0 += ((uint128_t) f2_19) * ((uint128_t) g3);
r0 += ((uint128_t) f3_19) * ((uint128_t) g2);
r0 += ((uint128_t) f4_19) * ((uint128_t) g1);
r1 = ((uint128_t) f0 ) * ((uint128_t) g1);
r1 += ((uint128_t) f1 ) * ((uint128_t) g0);
r1 += ((uint128_t) f2_19) * ((uint128_t) g4);
r1 += ((uint128_t) f3_19) * ((uint128_t) g3);
r1 += ((uint128_t) f4_19) * ((uint128_t) g2);
r2 = ((uint128_t) f0 ) * ((uint128_t) g2);
r2 += ((uint128_t) f1 ) * ((uint128_t) g1);
r2 += ((uint128_t) f2 ) * ((uint128_t) g0);
r2 += ((uint128_t) f3_19) * ((uint128_t) g4);
r2 += ((uint128_t) f4_19) * ((uint128_t) g3);
r3 = ((uint128_t) f0 ) * ((uint128_t) g3);
r3 += ((uint128_t) f1 ) * ((uint128_t) g2);
r3 += ((uint128_t) f2 ) * ((uint128_t) g1);
r3 += ((uint128_t) f3 ) * ((uint128_t) g0);
r3 += ((uint128_t) f4_19) * ((uint128_t) g4);
r4 = ((uint128_t) f0 ) * ((uint128_t) g4);
r4 += ((uint128_t) f1 ) * ((uint128_t) g3);
r4 += ((uint128_t) f2 ) * ((uint128_t) g2);
r4 += ((uint128_t) f3 ) * ((uint128_t) g1);
r4 += ((uint128_t) f4 ) * ((uint128_t) g0);
r00 = ((uint64_t) r0) & mask;
carry = r0 >> 51;
r1 += carry;
r01 = ((uint64_t) r1) & mask;
carry = r1 >> 51;
r2 += carry;
r02 = ((uint64_t) r2) & mask;
carry = r2 >> 51;
r3 += carry;
r03 = ((uint64_t) r3) & mask;
carry = r3 >> 51;
r4 += carry;
r04 = ((uint64_t) r4) & mask;
carry = r4 >> 51;
r00 += 19ULL * (uint64_t) carry;
carry = r00 >> 51;
r00 &= mask;
r01 += (uint64_t) carry;
carry = r01 >> 51;
r01 &= mask;
r02 += (uint64_t) carry;
h[0] = r00;
h[1] = r01;
h[2] = r02;
h[3] = r03;
h[4] = r04;
}
/*
h = f * f
Can overlap h with f.
*/
static void
fe25519_sq(fe25519 h, const fe25519 f)
{
const uint64_t mask = 0x7ffffffffffffULL;
uint128_t r0, r1, r2, r3, r4, carry;
uint64_t f0, f1, f2, f3, f4;
uint64_t f0_2, f1_2, f1_38, f2_38, f3_38, f3_19, f4_19;
uint64_t r00, r01, r02, r03, r04;
f0 = f[0];
f1 = f[1];
f2 = f[2];
f3 = f[3];
f4 = f[4];
f0_2 = f0 << 1;
f1_2 = f1 << 1;
f1_38 = 38ULL * f1;
f2_38 = 38ULL * f2;
f3_38 = 38ULL * f3;
f3_19 = 19ULL * f3;
f4_19 = 19ULL * f4;
r0 = ((uint128_t) f0 ) * ((uint128_t) f0);
r0 += ((uint128_t) f1_38) * ((uint128_t) f4);
r0 += ((uint128_t) f2_38) * ((uint128_t) f3);
r1 = ((uint128_t) f0_2 ) * ((uint128_t) f1);
r1 += ((uint128_t) f2_38) * ((uint128_t) f4);
r1 += ((uint128_t) f3_19) * ((uint128_t) f3);
r2 = ((uint128_t) f0_2 ) * ((uint128_t) f2);
r2 += ((uint128_t) f1 ) * ((uint128_t) f1);
r2 += ((uint128_t) f3_38) * ((uint128_t) f4);
r3 = ((uint128_t) f0_2 ) * ((uint128_t) f3);
r3 += ((uint128_t) f1_2 ) * ((uint128_t) f2);
r3 += ((uint128_t) f4_19) * ((uint128_t) f4);
r4 = ((uint128_t) f0_2 ) * ((uint128_t) f4);
r4 += ((uint128_t) f1_2 ) * ((uint128_t) f3);
r4 += ((uint128_t) f2 ) * ((uint128_t) f2);
r00 = ((uint64_t) r0) & mask;
carry = r0 >> 51;
r1 += carry;
r01 = ((uint64_t) r1) & mask;
carry = r1 >> 51;
r2 += carry;
r02 = ((uint64_t) r2) & mask;
carry = r2 >> 51;
r3 += carry;
r03 = ((uint64_t) r3) & mask;
carry = r3 >> 51;
r4 += carry;
r04 = ((uint64_t) r4) & mask;
carry = r4 >> 51;
r00 += 19ULL * (uint64_t) carry;
carry = r00 >> 51;
r00 &= mask;
r01 += (uint64_t) carry;
carry = r01 >> 51;
r01 &= mask;
r02 += (uint64_t) carry;
h[0] = r00;
h[1] = r01;
h[2] = r02;
h[3] = r03;
h[4] = r04;
}
/*
h = 2 * f * f
Can overlap h with f.
*/
static void
fe25519_sq2(fe25519 h, const fe25519 f)
{
const uint64_t mask = 0x7ffffffffffffULL;
uint128_t r0, r1, r2, r3, r4, carry;
uint64_t f0, f1, f2, f3, f4;
uint64_t f0_2, f1_2, f1_38, f2_38, f3_38, f3_19, f4_19;
uint64_t r00, r01, r02, r03, r04;
f0 = f[0];
f1 = f[1];
f2 = f[2];
f3 = f[3];
f4 = f[4];
f0_2 = f0 << 1;
f1_2 = f1 << 1;
f1_38 = 38ULL * f1;
f2_38 = 38ULL * f2;
f3_38 = 38ULL * f3;
f3_19 = 19ULL * f3;
f4_19 = 19ULL * f4;
r0 = ((uint128_t) f0 ) * ((uint128_t) f0);
r0 += ((uint128_t) f1_38) * ((uint128_t) f4);
r0 += ((uint128_t) f2_38) * ((uint128_t) f3);
r1 = ((uint128_t) f0_2 ) * ((uint128_t) f1);
r1 += ((uint128_t) f2_38) * ((uint128_t) f4);
r1 += ((uint128_t) f3_19) * ((uint128_t) f3);
r2 = ((uint128_t) f0_2 ) * ((uint128_t) f2);
r2 += ((uint128_t) f1 ) * ((uint128_t) f1);
r2 += ((uint128_t) f3_38) * ((uint128_t) f4);
r3 = ((uint128_t) f0_2 ) * ((uint128_t) f3);
r3 += ((uint128_t) f1_2 ) * ((uint128_t) f2);
r3 += ((uint128_t) f4_19) * ((uint128_t) f4);
r4 = ((uint128_t) f0_2 ) * ((uint128_t) f4);
r4 += ((uint128_t) f1_2 ) * ((uint128_t) f3);
r4 += ((uint128_t) f2 ) * ((uint128_t) f2);
r0 <<= 1;
r1 <<= 1;
r2 <<= 1;
r3 <<= 1;
r4 <<= 1;
r00 = ((uint64_t) r0) & mask;
carry = r0 >> 51;
r1 += carry;
r01 = ((uint64_t) r1) & mask;
carry = r1 >> 51;
r2 += carry;
r02 = ((uint64_t) r2) & mask;
carry = r2 >> 51;
r3 += carry;
r03 = ((uint64_t) r3) & mask;
carry = r3 >> 51;
r4 += carry;
r04 = ((uint64_t) r4) & mask;
carry = r4 >> 51;
r00 += 19ULL * (uint64_t) carry;
carry = r00 >> 51;
r00 &= mask;
r01 += (uint64_t) carry;
carry = r01 >> 51;
r01 &= mask;
r02 += (uint64_t) carry;
h[0] = r00;
h[1] = r01;
h[2] = r02;
h[3] = r03;
h[4] = r04;
}
static void
fe25519_scalar_product(fe25519 h, const fe25519 f, uint32_t n)
{
const uint64_t mask = 0x7ffffffffffffULL;
uint128_t a;
uint128_t sn = (uint128_t) n;
uint64_t h0, h1, h2, h3, h4;
a = f[0] * sn;
h0 = ((uint64_t) a) & mask;
a = f[1] * sn + ((uint64_t) (a >> 51));
h1 = ((uint64_t) a) & mask;
a = f[2] * sn + ((uint64_t) (a >> 51));
h2 = ((uint64_t) a) & mask;
a = f[3] * sn + ((uint64_t) (a >> 51));
h3 = ((uint64_t) a) & mask;
a = f[4] * sn + ((uint64_t) (a >> 51));
h4 = ((uint64_t) a) & mask;
h0 += (a >> 51) * 19ULL;
h[0] = h0;
h[1] = h1;
h[2] = h2;
h[3] = h3;
h[4] = h4;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
{
{ 25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605 },
{ -12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378 },
{ -8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546 }
},
{
{ 15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024 },
{ 16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574 },
{ 30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357 }
},
{
{ 10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380 },
{ 4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306 },
{ 19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942 }
},
{
{ 5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766 },
{ -30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701 },
{ 28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300 }
},
{
{ -22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877 },
{ -6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951 },
{ 4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784 }
},
{
{ -25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436 },
{ 25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918 },
{ 23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877 }
},
{
{ -33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800 },
{ -25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305 },
{ -13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300 }
},
{
{ -3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876 },
{ -24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619 },
{ -3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683 }
}

View File

@@ -0,0 +1,40 @@
/* 37095705934669439343138083508754565189542113879843219016388785533085940283555 */
static const fe25519 d = {
-10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116
};
/* 2 * d =
* 16295367250680780974490674513165176452449235426866156013048779062215315747161
*/
static const fe25519 d2 = {
-21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199 };
/* sqrt(-1) */
static const fe25519 sqrtm1 = {
-32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482
};
/* A = 486662 */
static const fe25519 curve25519_A = {
486662, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* sqrt(ad - 1) with a = -1 (mod p) */
static const fe25519 sqrtadm1 = {
24849947, -153582, -23613485, 6347715, -21072328, -667138, -25271143, -15367704, -870347, 14525639
};
/* 1 / sqrt(a - d) */
static const fe25519 invsqrtamd = {
6111485, 4156064, -27798727, 12243468, -25904040, 120897, 20826367, -7060776, 6093568, -1986012
};
/* 1 - d ^ 2 */
static const fe25519 onemsqd = {
6275446, -16617371, -22938544, -3773710, 11667077, 7397348, -27922721, 1766195, -24433858, 672203
};
/* (d - 1) ^ 2 */
static const fe25519 sqdmone = {
15551795, -11097455, -13425098, -10125071, -11896535, 10178284, -26634327, 4729244, -5282110, -10116402
};

View File

@@ -0,0 +1,220 @@
/*
Ignores top bit of h.
*/
void
fe25519_frombytes(fe25519 h, const unsigned char *s)
{
int64_t h0 = load_4(s);
int64_t h1 = load_3(s + 4) << 6;
int64_t h2 = load_3(s + 7) << 5;
int64_t h3 = load_3(s + 10) << 3;
int64_t h4 = load_3(s + 13) << 2;
int64_t h5 = load_4(s + 16);
int64_t h6 = load_3(s + 20) << 7;
int64_t h7 = load_3(s + 23) << 5;
int64_t h8 = load_3(s + 26) << 4;
int64_t h9 = (load_3(s + 29) & 8388607) << 2;
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;
carry9 = (h9 + (int64_t)(1L << 24)) >> 25;
h0 += carry9 * 19;
h9 -= carry9 * ((uint64_t) 1L << 25);
carry1 = (h1 + (int64_t)(1L << 24)) >> 25;
h2 += carry1;
h1 -= carry1 * ((uint64_t) 1L << 25);
carry3 = (h3 + (int64_t)(1L << 24)) >> 25;
h4 += carry3;
h3 -= carry3 * ((uint64_t) 1L << 25);
carry5 = (h5 + (int64_t)(1L << 24)) >> 25;
h6 += carry5;
h5 -= carry5 * ((uint64_t) 1L << 25);
carry7 = (h7 + (int64_t)(1L << 24)) >> 25;
h8 += carry7;
h7 -= carry7 * ((uint64_t) 1L << 25);
carry0 = (h0 + (int64_t)(1L << 25)) >> 26;
h1 += carry0;
h0 -= carry0 * ((uint64_t) 1L << 26);
carry2 = (h2 + (int64_t)(1L << 25)) >> 26;
h3 += carry2;
h2 -= carry2 * ((uint64_t) 1L << 26);
carry4 = (h4 + (int64_t)(1L << 25)) >> 26;
h5 += carry4;
h4 -= carry4 * ((uint64_t) 1L << 26);
carry6 = (h6 + (int64_t)(1L << 25)) >> 26;
h7 += carry6;
h6 -= carry6 * ((uint64_t) 1L << 26);
carry8 = (h8 + (int64_t)(1L << 25)) >> 26;
h9 += carry8;
h8 -= carry8 * ((uint64_t) 1L << 26);
h[0] = (int32_t) h0;
h[1] = (int32_t) h1;
h[2] = (int32_t) h2;
h[3] = (int32_t) h3;
h[4] = (int32_t) h4;
h[5] = (int32_t) h5;
h[6] = (int32_t) h6;
h[7] = (int32_t) h7;
h[8] = (int32_t) h8;
h[9] = (int32_t) h9;
}
/*
Preconditions:
|h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
Write p=2^255-19; q=floor(h/p).
Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
Proof:
Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4.
Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
Then 0<y<1.
Write r=h-pq.
Have 0<=r<=p-1=2^255-20.
Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
Write x=r+19(2^-255)r+y.
Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
*/
static void
fe25519_reduce(fe25519 h, const fe25519 f)
{
int32_t h0 = f[0];
int32_t h1 = f[1];
int32_t h2 = f[2];
int32_t h3 = f[3];
int32_t h4 = f[4];
int32_t h5 = f[5];
int32_t h6 = f[6];
int32_t h7 = f[7];
int32_t h8 = f[8];
int32_t h9 = f[9];
int32_t q;
int32_t carry0, carry1, carry2, carry3, carry4, carry5, carry6, carry7, carry8, carry9;
q = (19 * h9 + ((uint32_t) 1L << 24)) >> 25;
q = (h0 + q) >> 26;
q = (h1 + q) >> 25;
q = (h2 + q) >> 26;
q = (h3 + q) >> 25;
q = (h4 + q) >> 26;
q = (h5 + q) >> 25;
q = (h6 + q) >> 26;
q = (h7 + q) >> 25;
q = (h8 + q) >> 26;
q = (h9 + q) >> 25;
/* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */
h0 += 19 * q;
/* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
carry0 = h0 >> 26;
h1 += carry0;
h0 -= carry0 * ((uint32_t) 1L << 26);
carry1 = h1 >> 25;
h2 += carry1;
h1 -= carry1 * ((uint32_t) 1L << 25);
carry2 = h2 >> 26;
h3 += carry2;
h2 -= carry2 * ((uint32_t) 1L << 26);
carry3 = h3 >> 25;
h4 += carry3;
h3 -= carry3 * ((uint32_t) 1L << 25);
carry4 = h4 >> 26;
h5 += carry4;
h4 -= carry4 * ((uint32_t) 1L << 26);
carry5 = h5 >> 25;
h6 += carry5;
h5 -= carry5 * ((uint32_t) 1L << 25);
carry6 = h6 >> 26;
h7 += carry6;
h6 -= carry6 * ((uint32_t) 1L << 26);
carry7 = h7 >> 25;
h8 += carry7;
h7 -= carry7 * ((uint32_t) 1L << 25);
carry8 = h8 >> 26;
h9 += carry8;
h8 -= carry8 * ((uint32_t) 1L << 26);
carry9 = h9 >> 25;
h9 -= carry9 * ((uint32_t) 1L << 25);
h[0] = h0;
h[1] = h1;
h[2] = h2;
h[3] = h3;
h[4] = h4;
h[5] = h5;
h[6] = h6;
h[7] = h7;
h[8] = h8;
h[9] = h9;
}
/*
Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
Have h0+...+2^230 h9 between 0 and 2^255-1;
evidently 2^255 h10-2^255 q = 0.
Goal: Output h0+...+2^230 h9.
*/
void
fe25519_tobytes(unsigned char *s, const fe25519 h)
{
fe25519 t;
fe25519_reduce(t, h);
s[0] = t[0] >> 0;
s[1] = t[0] >> 8;
s[2] = t[0] >> 16;
s[3] = (t[0] >> 24) | (t[1] * ((uint32_t) 1 << 2));
s[4] = t[1] >> 6;
s[5] = t[1] >> 14;
s[6] = (t[1] >> 22) | (t[2] * ((uint32_t) 1 << 3));
s[7] = t[2] >> 5;
s[8] = t[2] >> 13;
s[9] = (t[2] >> 21) | (t[3] * ((uint32_t) 1 << 5));
s[10] = t[3] >> 3;
s[11] = t[3] >> 11;
s[12] = (t[3] >> 19) | (t[4] * ((uint32_t) 1 << 6));
s[13] = t[4] >> 2;
s[14] = t[4] >> 10;
s[15] = t[4] >> 18;
s[16] = t[5] >> 0;
s[17] = t[5] >> 8;
s[18] = t[5] >> 16;
s[19] = (t[5] >> 24) | (t[6] * ((uint32_t) 1 << 1));
s[20] = t[6] >> 7;
s[21] = t[6] >> 15;
s[22] = (t[6] >> 23) | (t[7] * ((uint32_t) 1 << 3));
s[23] = t[7] >> 5;
s[24] = t[7] >> 13;
s[25] = (t[7] >> 21) | (t[8] * ((uint32_t) 1 << 4));
s[26] = t[8] >> 4;
s[27] = t[8] >> 12;
s[28] = (t[8] >> 20) | (t[9] * ((uint32_t) 1 << 6));
s[29] = t[9] >> 2;
s[30] = t[9] >> 10;
s[31] = t[9] >> 18;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
{
{ 1288382639258501, 245678601348599, 269427782077623, 1462984067271730, 137412439391563 },
{ 62697248952638, 204681361388450, 631292143396476, 338455783676468, 1213667448819585 },
{ 301289933810280, 1259582250014073, 1422107436869536, 796239922652654, 1953934009299142 }
},
{
{ 1601611775252272, 1720807796594148, 1132070835939856, 1260455018889551, 2147779492816911 },
{ 316559037616741, 2177824224946892, 1459442586438991, 1461528397712656, 751590696113597 },
{ 1850748884277385, 1200145853858453, 1068094770532492, 672251375690438, 1586055907191707 }
},
{
{ 769950342298419, 132954430919746, 844085933195555, 974092374476333, 726076285546016 },
{ 425251763115706, 608463272472562, 442562545713235, 837766094556764, 374555092627893 },
{ 1086255230780037, 274979815921559, 1960002765731872, 929474102396301, 1190409889297339 }
},
{
{ 665000864555967, 2065379846933859, 370231110385876, 350988370788628, 1233371373142985 },
{ 2019367628972465, 676711900706637, 110710997811333, 1108646842542025, 517791959672113 },
{ 965130719900578, 247011430587952, 526356006571389, 91986625355052, 2157223321444601 }
},
{
{ 1802695059465007, 1664899123557221, 593559490740857, 2160434469266659, 927570450755031 },
{ 1725674970513508, 1933645953859181, 1542344539275782, 1767788773573747, 1297447965928905 },
{ 1381809363726107, 1430341051343062, 2061843536018959, 1551778050872521, 2036394857967624 }
},
{
{ 1970894096313054, 528066325833207, 1619374932191227, 2207306624415883, 1169170329061080 },
{ 2070390218572616, 1458919061857835, 624171843017421, 1055332792707765, 433987520732508 },
{ 893653801273833, 1168026499324677, 1242553501121234, 1306366254304474, 1086752658510815 }
},
{
{ 213454002618221, 939771523987438, 1159882208056014, 317388369627517, 621213314200687 },
{ 1971678598905747, 338026507889165, 762398079972271, 655096486107477, 42299032696322 },
{ 177130678690680, 1754759263300204, 1864311296286618, 1180675631479880, 1292726903152791 }
},
{
{ 1913163449625248, 460779200291993, 2193883288642314, 1008900146920800, 1721983679009502 },
{ 1070401523076875, 1272492007800961, 1910153608563310, 2075579521696771, 1191169788841221 },
{ 692896803108118, 500174642072499, 2068223309439677, 1162190621851337, 1426986007309901 }
}

View File

@@ -0,0 +1,41 @@
/* 37095705934669439343138083508754565189542113879843219016388785533085940283555 */
static const fe25519 d = {
929955233495203, 466365720129213, 1662059464998953, 2033849074728123, 1442794654840575
};
/* 2 * d =
* 16295367250680780974490674513165176452449235426866156013048779062215315747161
*/
static const fe25519 d2 = {
1859910466990425, 932731440258426, 1072319116312658, 1815898335770999, 633789495995903
};
/* sqrt(-1) */
static const fe25519 sqrtm1 = {
1718705420411056, 234908883556509, 2233514472574048, 2117202627021982, 765476049583133
};
/* A = 486662 */
static const fe25519 curve25519_A = {
486662, 0, 0, 0, 0
};
/* sqrt(ad - 1) with a = -1 (mod p) */
static const fe25519 sqrtadm1 = {
2241493124984347, 425987919032274, 2207028919301688, 1220490630685848, 974799131293748
};
/* 1 / sqrt(a - d) */
static const fe25519 invsqrtamd = {
278908739862762, 821645201101625, 8113234426968, 1777959178193151, 2118520810568447
};
/* 1 - d ^ 2 */
static const fe25519 onemsqd = {
1136626929484150, 1998550399581263, 496427632559748, 118527312129759, 45110755273534
};
/* (d - 1) ^ 2 */
static const fe25519 sqdmone = {
1507062230895904, 1572317787530805, 683053064812840, 317374165784489, 1572899562415810
};

View File

@@ -0,0 +1,116 @@
/*
Ignores top bit of h.
*/
void
fe25519_frombytes(fe25519 h, const unsigned char *s)
{
const uint64_t mask = 0x7ffffffffffffULL;
uint64_t h0, h1, h2, h3, h4;
h0 = (LOAD64_LE(s ) ) & mask;
h1 = (LOAD64_LE(s + 6) >> 3) & mask;
h2 = (LOAD64_LE(s + 12) >> 6) & mask;
h3 = (LOAD64_LE(s + 19) >> 1) & mask;
h4 = (LOAD64_LE(s + 24) >> 12) & mask;
h[0] = h0;
h[1] = h1;
h[2] = h2;
h[3] = h3;
h[4] = h4;
}
static void
fe25519_reduce(fe25519 h, const fe25519 f)
{
const uint64_t mask = 0x7ffffffffffffULL;
uint128_t t[5];
t[0] = f[0];
t[1] = f[1];
t[2] = f[2];
t[3] = f[3];
t[4] = f[4];
t[1] += t[0] >> 51;
t[0] &= mask;
t[2] += t[1] >> 51;
t[1] &= mask;
t[3] += t[2] >> 51;
t[2] &= mask;
t[4] += t[3] >> 51;
t[3] &= mask;
t[0] += 19 * (t[4] >> 51);
t[4] &= mask;
t[1] += t[0] >> 51;
t[0] &= mask;
t[2] += t[1] >> 51;
t[1] &= mask;
t[3] += t[2] >> 51;
t[2] &= mask;
t[4] += t[3] >> 51;
t[3] &= mask;
t[0] += 19 * (t[4] >> 51);
t[4] &= mask;
/* now t is between 0 and 2^255-1, properly carried. */
/* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */
t[0] += 19ULL;
t[1] += t[0] >> 51;
t[0] &= mask;
t[2] += t[1] >> 51;
t[1] &= mask;
t[3] += t[2] >> 51;
t[2] &= mask;
t[4] += t[3] >> 51;
t[3] &= mask;
t[0] += 19ULL * (t[4] >> 51);
t[4] &= mask;
/* now between 19 and 2^255-1 in both cases, and offset by 19. */
t[0] += 0x8000000000000 - 19ULL;
t[1] += 0x8000000000000 - 1ULL;
t[2] += 0x8000000000000 - 1ULL;
t[3] += 0x8000000000000 - 1ULL;
t[4] += 0x8000000000000 - 1ULL;
/* now between 2^255 and 2^256-20, and offset by 2^255. */
t[1] += t[0] >> 51;
t[0] &= mask;
t[2] += t[1] >> 51;
t[1] &= mask;
t[3] += t[2] >> 51;
t[2] &= mask;
t[4] += t[3] >> 51;
t[3] &= mask;
t[4] &= mask;
h[0] = t[0];
h[1] = t[1];
h[2] = t[2];
h[3] = t[3];
h[4] = t[4];
}
void
fe25519_tobytes(unsigned char *s, const fe25519 h)
{
fe25519 t;
uint64_t t0, t1, t2, t3;
fe25519_reduce(t, h);
t0 = t[0] | (t[1] << 51);
t1 = (t[1] >> 13) | (t[2] << 38);
t2 = (t[2] >> 26) | (t[3] << 25);
t3 = (t[3] >> 39) | (t[4] << 12);
STORE64_LE(s + 0, t0);
STORE64_LE(s + 8, t1);
STORE64_LE(s + 16, t2);
STORE64_LE(s + 24, t3);
}

View File

@@ -0,0 +1,209 @@
/*
* ISC License
*
* Copyright (c) 2013-2019
* Frank Denis <j at pureftpd dot org>
*
* 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.
*/
#include <stddef.h>
#include <stdint.h>
#include "ed25519_ref10.h"
#include "x25519_ref10.h"
#include "align.h"
/*
* Reject small order points early to mitigate the implications of
* unexpected optimizations that would affect the ref10 code.
* See https://eprint.iacr.org/2017/806.pdf for reference.
*/
static int
has_small_order(const unsigned char s[32])
{
CRYPTO_ALIGN(16)
static const unsigned char blacklist[][32] = {
/* 0 (order 4) */
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
/* 1 (order 1) */
{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
/* 325606250916557431795983626356110631294008115727848805560023387167927233504
(order 8) */
{ 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3,
0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32,
0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00 },
/* 39382357235489614581723060781553021112529911719440698176882885853963445705823
(order 8) */
{ 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 0xb1, 0xd0, 0xb1,
0x55, 0x9c, 0x83, 0xef, 0x5b, 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c,
0x8e, 0x86, 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57 },
/* p-1 (order 2) */
{ 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
/* p (=0, order 4) */
{ 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
/* p+1 (=1, order 1) */
{ 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }
};
unsigned char c[7] = { 0 };
unsigned int k;
size_t i, j;
#define COMPILER_ASSERT(X) (void) sizeof(char[(X) ? 1 : -1])
COMPILER_ASSERT(7 == sizeof blacklist / sizeof blacklist[0]);
for (j = 0; j < 31; j++) {
for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) {
c[i] |= s[j] ^ blacklist[i][j];
}
}
for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) {
c[i] |= (s[j] & 0x7f) ^ blacklist[i][j];
}
k = 0;
for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) {
k |= (c[i] - 1);
}
return (int) ((k >> 8) & 1);
}
static int
crypto_scalarmult_curve25519_ref10(unsigned char *q,
const unsigned char *n,
const unsigned char *p)
{
unsigned char *t = q;
unsigned int i;
fe25519 x1;
fe25519 x2;
fe25519 z2;
fe25519 x3;
fe25519 z3;
fe25519 tmp0;
fe25519 tmp1;
int pos;
unsigned int swap;
unsigned int b;
if (has_small_order(p)) {
return -1;
}
for (i = 0; i < 32; i++) {
t[i] = n[i];
}
t[0] &= 248;
t[31] &= 127;
t[31] |= 64;
fe25519_frombytes(x1, p);
fe25519_1(x2);
fe25519_0(z2);
fe25519_copy(x3, x1);
fe25519_1(z3);
swap = 0;
for (pos = 254; pos >= 0; --pos) {
b = t[pos / 8] >> (pos & 7);
b &= 1;
swap ^= b;
fe25519_cswap(x2, x3, swap);
fe25519_cswap(z2, z3, swap);
swap = b;
fe25519_sub(tmp0, x3, z3);
fe25519_sub(tmp1, x2, z2);
fe25519_add(x2, x2, z2);
fe25519_add(z2, x3, z3);
fe25519_mul(z3, tmp0, x2);
fe25519_mul(z2, z2, tmp1);
fe25519_sq(tmp0, tmp1);
fe25519_sq(tmp1, x2);
fe25519_add(x3, z3, z2);
fe25519_sub(z2, z3, z2);
fe25519_mul(x2, tmp1, tmp0);
fe25519_sub(tmp1, tmp1, tmp0);
fe25519_sq(z2, z2);
fe25519_scalar_product(z3, tmp1, 121666);
fe25519_sq(x3, x3);
fe25519_add(tmp0, tmp0, z3);
fe25519_mul(z3, x1, z2);
fe25519_mul(z2, tmp1, tmp0);
}
fe25519_cswap(x2, x3, swap);
fe25519_cswap(z2, z3, swap);
fe25519_invert(z2, z2);
fe25519_mul(x2, x2, z2);
fe25519_tobytes(q, x2);
return 0;
}
static void
edwards_to_montgomery(fe25519 montgomeryX, const fe25519 edwardsY, const fe25519 edwardsZ)
{
fe25519 tempX;
fe25519 tempZ;
fe25519_add(tempX, edwardsZ, edwardsY);
fe25519_sub(tempZ, edwardsZ, edwardsY);
fe25519_invert(tempZ, tempZ);
fe25519_mul(montgomeryX, tempX, tempZ);
}
int
crypto_scalarmult_curve25519_base(unsigned char *q,
const unsigned char *n)
{
unsigned char *t = q;
ge25519_p3 A;
fe25519 pk;
unsigned int i;
for (i = 0; i < 32; i++) {
t[i] = n[i];
}
t[0] &= 248;
t[31] &= 127;
t[31] |= 64;
ge25519_scalarmult_base(&A, t);
edwards_to_montgomery(pk, A.Y, A.Z);
fe25519_tobytes(q, pk);
return 0;
}
int
crypto_scalarmult_curve25519(unsigned char *q, const unsigned char *n,
const unsigned char *p)
{
size_t i;
volatile unsigned char d = 0;
if (crypto_scalarmult_curve25519_ref10(q, n, p) != 0) {
return -1; /* LCOV_EXCL_LINE */
}
for (i = 0; i < crypto_scalarmult_curve25519_BYTES; i++) {
d |= q[i];
}
return -(1 & ((d - 1) >> 8));
}

View File

@@ -0,0 +1,55 @@
/*
* ISC License
*
* Copyright (c) 2013-2019
* Frank Denis <j at pureftpd dot org>
*
* 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.
*/
#ifndef x25519_ref10_H
#define x25519_ref10_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define crypto_scalarmult_curve25519_BYTES 32U
size_t crypto_scalarmult_curve25519_bytes(void);
#define crypto_scalarmult_curve25519_SCALARBYTES 32U
size_t crypto_scalarmult_curve25519_scalarbytes(void);
/*
* NOTE: Do not use the result of this function directly for key exchange.
*
* Hash the result with the public keys in order to compute a shared
* secret key: H(q || client_pk || server_pk)
*
* Or unless this is not an option, use the crypto_kx() API instead.
*/
#define crypto_scalarmult_curve25519 hc_hcrypto_scalarmult_curve25519
int crypto_scalarmult_curve25519(unsigned char *q, const unsigned char *n,
const unsigned char *p);
#define crypto_scalarmult_curve25519_base hc_hcrypto_scalarmult_curve25519_base
int crypto_scalarmult_curve25519_base(unsigned char *q,
const unsigned char *n);
#ifdef __cplusplus
}
#endif
#endif