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:

committed by
Nicolas Williams

parent
20f9b2be48
commit
beda11a079
@@ -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)
|
||||
|
@@ -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))
|
||||
|
@@ -350,4 +350,5 @@ EXPORTS
|
||||
hc_EVP_CipherFinal_ex
|
||||
|
||||
hc_hcrypto_validate
|
||||
|
||||
hc_hcrypto_scalarmult_curve25519
|
||||
hc_hcrypto_scalarmult_curve25519_base
|
||||
|
@@ -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:
|
||||
*;
|
||||
};
|
||||
|
46
lib/hcrypto/x25519/NTMakefile
Normal file
46
lib/hcrypto/x25519/NTMakefile
Normal 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)
|
||||
|
7
lib/hcrypto/x25519/align.h
Normal file
7
lib/hcrypto/x25519/align.h
Normal 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
|
2886
lib/hcrypto/x25519/ed25519_ref10.c
Normal file
2886
lib/hcrypto/x25519/ed25519_ref10.c
Normal file
File diff suppressed because it is too large
Load Diff
174
lib/hcrypto/x25519/ed25519_ref10.h
Normal file
174
lib/hcrypto/x25519/ed25519_ref10.h
Normal 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
|
1067
lib/hcrypto/x25519/ed25519_ref10_fe_25_5.h
Normal file
1067
lib/hcrypto/x25519/ed25519_ref10_fe_25_5.h
Normal file
File diff suppressed because it is too large
Load Diff
539
lib/hcrypto/x25519/ed25519_ref10_fe_51.h
Normal file
539
lib/hcrypto/x25519/ed25519_ref10_fe_51.h
Normal 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;
|
||||
}
|
1344
lib/hcrypto/x25519/fe_25_5/base.h
Normal file
1344
lib/hcrypto/x25519/fe_25_5/base.h
Normal file
File diff suppressed because it is too large
Load Diff
40
lib/hcrypto/x25519/fe_25_5/base2.h
Normal file
40
lib/hcrypto/x25519/fe_25_5/base2.h
Normal 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 }
|
||||
}
|
40
lib/hcrypto/x25519/fe_25_5/constants.h
Normal file
40
lib/hcrypto/x25519/fe_25_5/constants.h
Normal 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
|
||||
};
|
220
lib/hcrypto/x25519/fe_25_5/fe.h
Normal file
220
lib/hcrypto/x25519/fe_25_5/fe.h
Normal 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;
|
||||
}
|
1344
lib/hcrypto/x25519/fe_51/base.h
Normal file
1344
lib/hcrypto/x25519/fe_51/base.h
Normal file
File diff suppressed because it is too large
Load Diff
40
lib/hcrypto/x25519/fe_51/base2.h
Normal file
40
lib/hcrypto/x25519/fe_51/base2.h
Normal 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 }
|
||||
}
|
41
lib/hcrypto/x25519/fe_51/constants.h
Normal file
41
lib/hcrypto/x25519/fe_51/constants.h
Normal 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
|
||||
};
|
116
lib/hcrypto/x25519/fe_51/fe.h
Normal file
116
lib/hcrypto/x25519/fe_51/fe.h
Normal 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);
|
||||
}
|
209
lib/hcrypto/x25519/x25519_ref10.c
Normal file
209
lib/hcrypto/x25519/x25519_ref10.c
Normal 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));
|
||||
}
|
||||
|
55
lib/hcrypto/x25519_ref10.h
Normal file
55
lib/hcrypto/x25519_ref10.h
Normal 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
|
Reference in New Issue
Block a user