Curve25519: improved smul

Use the Ed25519 base smul in Curve25519 base mul and covert to
Montogmery curve for a faster implementation.
Only when Ed25519 is compiled in or WOLFSSL_CURVE25519_USE_ED25519 is
defined.
When compiling Intel x64 assembly and Aarch64 assembly, always define
WOLFSSL_CURVE25519_USE_ED25519.
Can't use with blinding - normal C implementation.

Optimized the Curve25519 smul slightly for Intel x64 and Aarch64.
Improved the conditional table lookup on Intel x64 to use AVX2 when
available.
This commit is contained in:
Sean Parkinson
2025-12-17 13:25:36 +10:00
parent ab2196b4ca
commit f54266c2c6
15 changed files with 12791 additions and 897 deletions

View File

@@ -10275,6 +10275,12 @@ then
AM_CFLAGS="$AM_CFLAGS -DNO_CURVED25519_128BIT"
fi
if test "$ENABLED_CURVE25519" = "ed"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CURVE25519_USE_ED25519"
AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_CURVE25519_USE_ED25519"
fi
AM_CFLAGS="$AM_CFLAGS -DHAVE_CURVE25519"
AM_CCASFLAGS="$AM_CCASFLAGS -DHAVE_CURVE25519"
ENABLED_FEMATH=yes

View File

@@ -1401,6 +1401,7 @@ endif !BUILD_FIPS_V6_PLUS
if BUILD_FEMATH
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/fe_low_mem.c
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/ge_operations.c
if BUILD_CURVE25519_INTELASM
if !BUILD_X86_ASM
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/fe_x25519_asm.S
@@ -1460,8 +1461,8 @@ endif BUILD_FEMATH
if BUILD_GEMATH
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/ge_low_mem.c
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/ge_operations.c
if !BUILD_FEMATH
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/ge_operations.c
if BUILD_CURVE25519_INTELASM
if !BUILD_X86_ASM
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/fe_x25519_asm.S

View File

@@ -31,6 +31,7 @@
#ifdef HAVE_CURVE25519
#include <wolfssl/wolfcrypt/curve25519.h>
#include <wolfssl/wolfcrypt/ge_operations.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
@@ -54,6 +55,8 @@
#error "Blinding not needed nor available for small implementation"
#elif defined(USE_INTEL_SPEEDUP) || defined(WOLFSSL_ARMASM)
#error "Blinding not needed nor available for assembly implementation"
#elif defined(WOLFSSL_CURVE25519_USE_ED25519)
#error "Ed25519 base scalar mult cannot be used with blinding "
#endif
#endif
@@ -72,6 +75,8 @@ const curve25519_set_type curve25519_sets[] = {
}
};
#if !defined(WOLFSSL_CURVE25519_USE_ED25519) || \
defined(WOLFSSL_CURVE25519_BLINDING)
static const word32 kCurve25519BasePoint[CURVE25519_KEYSIZE/sizeof(word32)] = {
#ifdef BIG_ENDIAN_ORDER
0x09000000
@@ -79,6 +84,7 @@ static const word32 kCurve25519BasePoint[CURVE25519_KEYSIZE/sizeof(word32)] = {
9
#endif
};
#endif /* !WOLFSSL_CURVE25519_USE_ED25519 || WOLFSSL_CURVE25519_BLINDING */
/* Curve25519 private key must be less than order */
/* These functions clamp private k and check it */
@@ -154,7 +160,31 @@ int wc_curve25519_make_pub(int public_size, byte* pub, int private_size,
SAVE_VECTOR_REGISTERS(return _svr_ret;);
#if defined(WOLFSSL_CURVE25519_USE_ED25519)
{
ge_p3 A;
ge_scalarmult_base(&A, priv);
#ifndef CURVE25519_SMALL
fe_add(A.X, A.Z, A.Y);
fe_sub(A.T, A.Z, A.Y);
fe_invert(A.T, A.T);
fe_mul(A.T, A.X, A.T);
fe_tobytes(pub, A.T);
#else
lm_add(A.X, A.Z, A.Y);
lm_sub(A.T, A.Z, A.Y);
lm_invert(A.T, A.T);
lm_mul(pub, A.X, A.T);
#endif
ret = 0;
}
#elif defined(CURVED25519_X64) || (defined(WOLFSSL_ARMASM) && \
defined(__aarch64__))
ret = curve25519_base(pub, priv);
#else
ret = curve25519(pub, priv, (byte*)kCurve25519BasePoint);
#endif
RESTORE_VECTOR_REGISTERS();
#else

View File

@@ -88,13 +88,7 @@ static int ed25519_hash_init(ed25519_key* key, wc_Sha512 *sha)
{
int ret;
#ifndef WOLFSSL_ED25519_PERSISTENT_SHA
/* when not using persistent SHA, we'll zero the sha param */
XMEMSET(sha, 0, sizeof(wc_Sha512));
#endif
ret = wc_InitSha512_ex(sha, key->heap,
#if defined(WOLF_CRYPTO_CB)
key->devId
#else
@@ -103,8 +97,9 @@ static int ed25519_hash_init(ed25519_key* key, wc_Sha512 *sha)
);
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
if (ret == 0)
if (ret == 0) {
key->sha_clean_flag = 1;
}
#endif
return ret;
@@ -114,8 +109,10 @@ static int ed25519_hash_init(ed25519_key* key, wc_Sha512 *sha)
static int ed25519_hash_reset(ed25519_key* key)
{
int ret;
if (key->sha_clean_flag)
if (key->sha_clean_flag) {
ret = 0;
}
else {
wc_Sha512Free(&key->sha);
ret = wc_InitSha512_ex(&key->sha, key->heap,
@@ -128,6 +125,7 @@ static int ed25519_hash_reset(ed25519_key* key)
if (ret == 0)
key->sha_clean_flag = 1;
}
return ret;
}
#endif /* WOLFSSL_ED25519_PERSISTENT_SHA */
@@ -136,8 +134,9 @@ static int ed25519_hash_update(ed25519_key* key, wc_Sha512 *sha,
const byte* data, word32 len)
{
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
if (key->sha_clean_flag)
if (key->sha_clean_flag) {
key->sha_clean_flag = 0;
}
#else
(void)key;
#endif
@@ -148,8 +147,9 @@ static int ed25519_hash_final(ed25519_key* key, wc_Sha512 *sha, byte* hash)
{
int ret = wc_Sha512Final(sha, hash);
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
if (ret == 0)
if (ret == 0) {
key->sha_clean_flag = 1;
}
#else
(void)key;
#endif
@@ -187,16 +187,15 @@ static int ed25519_hash(ed25519_key* key, const byte* in, word32 inLen,
#else
ret = ed25519_hash_init(key, sha);
#endif
if (ret < 0)
return ret;
if (ret == 0) {
ret = ed25519_hash_update(key, sha, in, inLen);
if (ret == 0)
ret = ed25519_hash_final(key, sha, hash);
ret = ed25519_hash_update(key, sha, in, inLen);
if (ret == 0)
ret = ed25519_hash_final(key, sha, hash);
#ifndef WOLFSSL_ED25519_PERSISTENT_SHA
ed25519_hash_free(key, sha);
#endif
#ifndef WOLFSSL_ED25519_PERSISTENT_SHA
ed25519_hash_free(key, sha);
#endif
}
return ret;
}

File diff suppressed because it is too large Load Diff

View File

@@ -24,10 +24,11 @@
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
#ifdef HAVE_ED25519
#include <wolfssl/wolfcrypt/ge_operations.h>
#if defined(HAVE_ED25519) || defined(WOLFSSL_CURVE25519_USE_ED25519)
#ifndef ED25519_SMALL /* run when not defined to use small memory math */
#include <wolfssl/wolfcrypt/ge_operations.h>
#include <wolfssl/wolfcrypt/ed25519.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
@@ -52,7 +53,8 @@
static void ge_p2_0(ge_p2 *h);
#ifndef CURVED25519_ASM
#if defined(HAVE_ED25519_SIGN) || defined(HAVE_ED25519_MAKE_KEY)
#if defined(HAVE_ED25519_SIGN) || defined(HAVE_ED25519_MAKE_KEY) || \
defined(WOLFSSL_CURVE25519_USE_ED25519)
static void ge_precomp_0(ge_precomp *h);
#endif
static void ge_p3_to_p2(ge_p2 *r,const ge_p3 *p);
@@ -968,7 +970,8 @@ static unsigned char equal(unsigned char b,unsigned char c)
return (unsigned char)y;
}
#if defined(HAVE_ED25519_SIGN) || defined(HAVE_ED25519_MAKE_KEY)
#if defined(HAVE_ED25519_SIGN) || defined(HAVE_ED25519_MAKE_KEY) || \
defined(WOLFSSL_CURVE25519_USE_ED25519)
static unsigned char negative(signed char b)
{
return ((unsigned char)b) >> 7;
@@ -986,7 +989,8 @@ static WC_INLINE void cmov(ge_precomp *t,const ge_precomp *u,unsigned char b,
}
#endif
#if defined(HAVE_ED25519_SIGN) || defined(HAVE_ED25519_MAKE_KEY)
#if defined(HAVE_ED25519_SIGN) || defined(HAVE_ED25519_MAKE_KEY) || \
defined(WOLFSSL_CURVE25519_USE_ED25519)
#ifdef CURVED25519_ASM_64BIT
static const ge_precomp base[64][8] = {
{
@@ -9066,7 +9070,6 @@ static const ge_precomp base[32][8] = {
} ;
#endif
static void ge_select(ge_precomp *t,int pos,signed char b)
{
#ifndef CURVED25519_ASM
@@ -9165,7 +9168,8 @@ void ge_scalarmult_base(ge_p3 *h,const unsigned char *a)
}
#endif
}
#endif /* HAVE_ED25519_SIGN || HAVE_ED25519_MAKE_KEY */
#endif /* HAVE_ED25519_SIGN || HAVE_ED25519_MAKE_KEY ||
* WOLFSSL_CURVE25519_USE_ED25519 */
#define SLIDE_SIZE 256
@@ -9769,7 +9773,8 @@ void ge_p3_tobytes(unsigned char *s,const ge_p3 *h)
#ifndef CURVED25519_ASM
#if defined(HAVE_ED25519_SIGN) || defined(HAVE_ED25519_MAKE_KEY)
#if defined(HAVE_ED25519_SIGN) || defined(HAVE_ED25519_MAKE_KEY) || \
defined(WOLFSSL_CURVE25519_USE_ED25519)
/* ge_precomp_0 */
static void ge_precomp_0(ge_precomp *h)
{

View File

@@ -345,7 +345,7 @@ fe_add:
bl fe_add_op
pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}
.size fe_add,.-fe_add
#ifdef HAVE_ED25519
#if defined(HAVE_ED25519) || defined(WOLFSSL_CURVE25519_USE_ED25519)
.text
.align 4
.globl fe_frombytes
@@ -590,7 +590,7 @@ fe_isnegative:
eor r0, r0, r1
pop {r4, r5, pc}
.size fe_isnegative,.-fe_isnegative
#if defined(HAVE_ED25519_MAKE_KEY) || defined(HAVE_ED25519_SIGN)
#if defined(HAVE_ED25519_MAKE_KEY) || defined(HAVE_ED25519_SIGN) || defined(WOLFSSL_CURVE25519_USE_ED25519)
#ifndef WC_NO_CACHE_RESISTANT
.text
.align 4
@@ -2235,8 +2235,8 @@ fe_cmov_table:
pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}
.size fe_cmov_table,.-fe_cmov_table
#endif /* WC_NO_CACHE_RESISTANT */
#endif /* HAVE_ED25519_MAKE_KEY || HAVE_ED25519_SIGN */
#endif /* HAVE_ED25519 */
#endif /* HAVE_ED25519_MAKE_KEY || HAVE_ED25519_SIGN || WOLFSSL_CURVE25519_USE_ED25519 */
#endif /* HAVE_ED25519 || WOLFSSL_CURVE25519_USE_ED25519 */
#if defined(WOLFSSL_ARM_ARCH) && (WOLFSSL_ARM_ARCH < 6)
.text
.align 4
@@ -3981,7 +3981,7 @@ L_curve25519_inv_8:
.size curve25519,.-curve25519
#endif /* WC_NO_CACHE_RESISTANT */
#endif /* HAVE_CURVE25519 */
#ifdef HAVE_ED25519
#if defined(HAVE_ED25519) || defined(WOLFSSL_CURVE25519_USE_ED25519)
.text
.align 4
.globl fe_invert
@@ -5217,6 +5217,8 @@ ge_sub:
add sp, sp, #44
pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}
.size ge_sub,.-ge_sub
#endif /* HAVE_ED25519 || WOLFSSL_CURVE25519_USE_ED25519 */
#ifdef HAVE_ED25519
#if defined(WOLFSSL_ARM_ARCH) && (WOLFSSL_ARM_ARCH < 6)
.text
.align 4

View File

@@ -459,7 +459,7 @@ WC_OMIT_FRAME_POINTER void fe_add(fe r, const fe a, const fe b)
);
}
#ifdef HAVE_ED25519
#if defined(HAVE_ED25519) || defined(WOLFSSL_CURVE25519_USE_ED25519)
#ifndef WOLFSSL_NO_VAR_ASSIGN_REG
WC_OMIT_FRAME_POINTER void fe_frombytes(fe out_p, const unsigned char* in_p)
#else
@@ -823,7 +823,8 @@ WC_OMIT_FRAME_POINTER int fe_isnegative(const fe a)
return (word32)(size_t)a;
}
#if defined(HAVE_ED25519_MAKE_KEY) || defined(HAVE_ED25519_SIGN)
#if defined(HAVE_ED25519_MAKE_KEY) || defined(HAVE_ED25519_SIGN) || \
defined(WOLFSSL_CURVE25519_USE_ED25519)
#ifndef WC_NO_CACHE_RESISTANT
#ifndef WOLFSSL_NO_VAR_ASSIGN_REG
WC_OMIT_FRAME_POINTER void fe_cmov_table(fe* r_p, fe* base_p, signed char b_p)
@@ -2502,8 +2503,9 @@ WC_OMIT_FRAME_POINTER void fe_cmov_table(fe* r, fe* base, signed char b)
}
#endif /* WC_NO_CACHE_RESISTANT */
#endif /* HAVE_ED25519_MAKE_KEY || HAVE_ED25519_SIGN */
#endif /* HAVE_ED25519 */
#endif /* HAVE_ED25519_MAKE_KEY || HAVE_ED25519_SIGN ||
* WOLFSSL_CURVE25519_USE_ED25519 */
#endif /* HAVE_ED25519 || WOLFSSL_CURVE25519_USE_ED25519 */
#if defined(WOLFSSL_ARM_ARCH) && (WOLFSSL_ARM_ARCH < 6)
void fe_mul_op(void);
#ifndef WOLFSSL_NO_VAR_ASSIGN_REG
@@ -4422,7 +4424,7 @@ WC_OMIT_FRAME_POINTER int curve25519(byte* r, const byte* n, const byte* a)
#endif /* WC_NO_CACHE_RESISTANT */
#endif /* HAVE_CURVE25519 */
#ifdef HAVE_ED25519
#if defined(HAVE_ED25519) || defined(WOLFSSL_CURVE25519_USE_ED25519)
#ifndef WOLFSSL_NO_VAR_ASSIGN_REG
WC_OMIT_FRAME_POINTER void fe_invert(fe r_p, const fe a_p)
#else
@@ -5860,6 +5862,8 @@ WC_OMIT_FRAME_POINTER void ge_sub(ge_p1p1 * r, const ge_p3 * p,
);
}
#endif /* HAVE_ED25519 || WOLFSSL_CURVE25519_USE_ED25519 */
#ifdef HAVE_ED25519
#if defined(WOLFSSL_ARM_ARCH) && (WOLFSSL_ARM_ARCH < 6)
#ifndef WOLFSSL_NO_VAR_ASSIGN_REG
WC_OMIT_FRAME_POINTER void sc_reduce(byte* s_p)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -227,7 +227,7 @@ fe_add:
POP {r4, r5, r6, r7, r8, r9, r10, r11, pc}
/* Cycle Count = 24 */
.size fe_add,.-fe_add
#ifdef HAVE_ED25519
#if defined(HAVE_ED25519) || defined(WOLFSSL_CURVE25519_USE_ED25519)
.text
.align 4
.globl fe_frombytes
@@ -430,7 +430,7 @@ fe_isnegative:
POP {r4, r5, pc}
/* Cycle Count = 31 */
.size fe_isnegative,.-fe_isnegative
#if defined(HAVE_ED25519_MAKE_KEY) || defined(HAVE_ED25519_SIGN)
#if defined(HAVE_ED25519_MAKE_KEY) || defined(HAVE_ED25519_SIGN) || defined(WOLFSSL_CURVE25519_USE_ED25519)
#ifndef WC_NO_CACHE_RESISTANT
.text
.align 4
@@ -1507,8 +1507,8 @@ fe_cmov_table:
/* Cycle Count = 160 */
.size fe_cmov_table,.-fe_cmov_table
#endif /* WC_NO_CACHE_RESISTANT */
#endif /* HAVE_ED25519_MAKE_KEY || HAVE_ED25519_SIGN */
#endif /* HAVE_ED25519 */
#endif /* HAVE_ED25519_MAKE_KEY || HAVE_ED25519_SIGN || WOLFSSL_CURVE25519_USE_ED25519 */
#endif /* HAVE_ED25519 || WOLFSSL_CURVE25519_USE_ED25519 */
#ifdef WOLFSSL_ARM_ARCH_7M
.text
.align 4
@@ -3272,7 +3272,7 @@ L_curve25519_inv_8:
.size curve25519,.-curve25519
#endif /* WC_NO_CACHE_RESISTANT */
#endif /* HAVE_CURVE25519 */
#ifdef HAVE_ED25519
#if defined(HAVE_ED25519) || defined(WOLFSSL_CURVE25519_USE_ED25519)
.text
.align 4
.globl fe_invert
@@ -4533,6 +4533,8 @@ ge_sub:
POP {r4, r5, r6, r7, r8, r9, r10, r11, pc}
/* Cycle Count = 138 */
.size ge_sub,.-ge_sub
#endif /* HAVE_ED25519 || WOLFSSL_CURVE25519_USE_ED25519 */
#ifdef HAVE_ED25519
#ifdef WOLFSSL_ARM_ARCH_7M
.text
.align 4

View File

@@ -296,7 +296,7 @@ WC_OMIT_FRAME_POINTER void fe_add(fe r, const fe a, const fe b)
);
}
#ifdef HAVE_ED25519
#if defined(HAVE_ED25519) || defined(WOLFSSL_CURVE25519_USE_ED25519)
#ifndef WOLFSSL_NO_VAR_ASSIGN_REG
WC_OMIT_FRAME_POINTER void fe_frombytes(fe out_p, const unsigned char* in_p)
#else
@@ -571,7 +571,7 @@ WC_OMIT_FRAME_POINTER int fe_isnegative(const fe a)
return (word32)(size_t)a;
}
#if defined(HAVE_ED25519_MAKE_KEY) || defined(HAVE_ED25519_SIGN)
#if defined(HAVE_ED25519_MAKE_KEY) || defined(HAVE_ED25519_SIGN) || defined(WOLFSSL_CURVE25519_USE_ED25519)
#ifndef WC_NO_CACHE_RESISTANT
#ifndef WOLFSSL_NO_VAR_ASSIGN_REG
WC_OMIT_FRAME_POINTER void fe_cmov_table(fe* r_p, fe* base_p, signed char b_p)
@@ -1670,8 +1670,8 @@ WC_OMIT_FRAME_POINTER void fe_cmov_table(fe* r, fe* base, signed char b)
}
#endif /* WC_NO_CACHE_RESISTANT */
#endif /* HAVE_ED25519_MAKE_KEY || HAVE_ED25519_SIGN */
#endif /* HAVE_ED25519 */
#endif /* HAVE_ED25519_MAKE_KEY || HAVE_ED25519_SIGN || WOLFSSL_CURVE25519_USE_ED25519 */
#endif /* HAVE_ED25519 || WOLFSSL_CURVE25519_USE_ED25519 */
#ifdef WOLFSSL_ARM_ARCH_7M
void fe_mul_op(void);
#ifndef WOLFSSL_NO_VAR_ASSIGN_REG
@@ -3663,7 +3663,7 @@ WC_OMIT_FRAME_POINTER int curve25519(byte* r, const byte* n, const byte* a)
#endif /* WC_NO_CACHE_RESISTANT */
#endif /* HAVE_CURVE25519 */
#ifdef HAVE_ED25519
#if defined(HAVE_ED25519) || defined(WOLFSSL_CURVE25519_USE_ED25519)
#ifndef WOLFSSL_NO_VAR_ASSIGN_REG
WC_OMIT_FRAME_POINTER void fe_invert(fe r_p, const fe a_p)
#else
@@ -5156,6 +5156,8 @@ WC_OMIT_FRAME_POINTER void ge_sub(ge_p1p1 * r, const ge_p3 * p,
);
}
#endif /* HAVE_ED25519 || WOLFSSL_CURVE25519_USE_ED25519 */
#ifdef HAVE_ED25519
#ifdef WOLFSSL_ARM_ARCH_7M
#ifndef WOLFSSL_NO_VAR_ASSIGN_REG
WC_OMIT_FRAME_POINTER void sc_reduce(byte* s_p)

View File

@@ -29,7 +29,7 @@
#include <wolfssl/wolfcrypt/types.h>
#ifdef HAVE_ED25519
#if defined(HAVE_ED25519) || defined(WOLFSSL_CURVE25519_USE_ED25519)
#include <wolfssl/wolfcrypt/random.h>
#ifndef WOLFSSL_SHA512

View File

@@ -48,6 +48,12 @@
#define CURVED25519_ASM
#endif
#if (defined(CURVED25519_ASM_64BIT) || defined(HAVE_ED25519)) && \
!defined(WOLFSSL_CURVE25519_BLINDING)
#undef WOLFSSL_CURVE25519_USE_ED25519
#define WOLFSSL_CURVE25519_USE_ED25519
#endif
/*
fe means field element.
Here the field is \Z/(2^255-19).
@@ -75,6 +81,7 @@ Bounds on each t[i] vary depending on context.
#if !defined(FREESCALE_LTC_ECC)
WOLFSSL_LOCAL void fe_init(void);
WOLFSSL_LOCAL int curve25519_base(byte * q, const byte * n);
WOLFSSL_LOCAL int curve25519(byte * q, const byte * n, const byte * p);
#ifdef WOLFSSL_CURVE25519_BLINDING
WOLFSSL_LOCAL int curve25519_blind(byte * q, const byte * n, const byte* mask,

View File

@@ -27,10 +27,10 @@
#include <wolfssl/wolfcrypt/settings.h>
#ifdef HAVE_ED25519
#include <wolfssl/wolfcrypt/fe_operations.h>
#if defined(HAVE_ED25519) || defined(WOLFSSL_CURVE25519_USE_ED25519)
/*
ge means group element.