Merge pull request #10955 from padelsbach/curve25519-cryptocb-only-full

Extend curve25519 crypto cb and cb-only for footprint savings
This commit is contained in:
David Garske
2026-08-04 18:46:35 -07:00
committed by GitHub
10 changed files with 248 additions and 20 deletions
+63
View File
@@ -576,6 +576,69 @@ int test_wc_curve25519_make_pub(void)
return EXPECT_RESULT();
} /* END test_wc_curve25519_make_pub */
/*
* Positive cross-check of the make_pub, generic and keygen paths (and the
* crypto-callback dispatch for each under WOLF_CRYPTO_CB_ONLY_CURVE25519):
* a public key from make_pub or from generic against base point 9 must match
* the make_key public point, and a shared secret must round trip.
*/
int test_wc_curve25519_make_pub_generic(void)
{
EXPECT_DECLS;
#if defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_SHARED_SECRET)
curve25519_key keyA;
curve25519_key keyB;
WC_RNG rng;
byte pubM[CURVE25519_KEYSIZE];
byte pubG[CURVE25519_KEYSIZE];
const byte base9[CURVE25519_KEYSIZE] = { 9 };
byte genAB[CURVE25519_KEYSIZE];
byte ssAB[CURVE25519_KEYSIZE];
byte ssBA[CURVE25519_KEYSIZE];
word32 ssABLen = (word32)sizeof(ssAB);
word32 ssBALen = (word32)sizeof(ssBA);
XMEMSET(&rng, 0, sizeof(WC_RNG));
ExpectIntEQ(wc_curve25519_init(&keyA), 0);
ExpectIntEQ(wc_curve25519_init(&keyB), 0);
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE, &keyA), 0);
ExpectIntEQ(wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE, &keyB), 0);
/* make_pub from the private scalar must match the keygen public point */
ExpectIntEQ(wc_curve25519_make_pub((int)sizeof(pubM), pubM,
(int)sizeof(keyA.k), keyA.k), 0);
ExpectBufEQ(pubM, keyA.p.point, CURVE25519_KEYSIZE);
/* generic against base point 9 is the same operation as make_pub */
ExpectIntEQ(wc_curve25519_generic((int)sizeof(pubG), pubG,
(int)sizeof(keyA.k), keyA.k, (int)sizeof(base9), base9), 0);
ExpectBufEQ(pubG, pubM, CURVE25519_KEYSIZE);
/* generic against B's public point must equal the A-B shared secret,
* proving generic actually uses the supplied base point */
ExpectIntEQ(wc_curve25519_generic((int)sizeof(genAB), genAB,
(int)sizeof(keyA.k), keyA.k,
(int)sizeof(keyB.p.point), keyB.p.point), 0);
ExpectIntEQ(wc_curve25519_shared_secret_ex(&keyA, &keyB, ssAB, &ssABLen,
EC25519_LITTLE_ENDIAN), 0);
ExpectBufEQ(genAB, ssAB, CURVE25519_KEYSIZE);
/* shared secret must agree both ways, proving the generated keys are
* mutually consistent (a degenerate result is rejected by shared_secret) */
ExpectIntEQ(wc_curve25519_shared_secret_ex(&keyB, &keyA, ssBA, &ssBALen,
EC25519_LITTLE_ENDIAN), 0);
ExpectBufEQ(ssBA, ssAB, CURVE25519_KEYSIZE);
DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_curve25519_free(&keyA);
wc_curve25519_free(&keyB);
#endif
return EXPECT_RESULT();
} /* END test_wc_curve25519_make_pub_generic */
/*
* Testing test_wc_curve25519_export_public_ex
*/
+2
View File
@@ -33,6 +33,7 @@ int test_wc_curve25519_shared_secret_ex(void);
int test_wc_curve25519_shared_secret_zero_check(void);
int test_wc_curve25519_shared_secret_ex_kat(void);
int test_wc_curve25519_make_pub(void);
int test_wc_curve25519_make_pub_generic(void);
int test_wc_curve25519_export_public_ex(void);
int test_wc_curve25519_export_private_raw_ex(void);
int test_wc_curve25519_import_private_raw_ex(void);
@@ -57,6 +58,7 @@ int test_wc_curve25519_nonblock(void);
TEST_DECL_GROUP("curve25519", test_wc_curve25519_shared_secret_zero_check),\
TEST_DECL_GROUP("curve25519", test_wc_curve25519_shared_secret_ex_kat), \
TEST_DECL_GROUP("curve25519", test_wc_curve25519_make_pub), \
TEST_DECL_GROUP("curve25519", test_wc_curve25519_make_pub_generic), \
TEST_DECL_GROUP("curve25519", test_wc_curve25519_export_public_ex), \
TEST_DECL_GROUP("curve25519", test_wc_curve25519_export_private_raw_ex), \
TEST_DECL_GROUP("curve25519", test_wc_curve25519_import_private_raw_ex), \
+22
View File
@@ -336,6 +336,24 @@ static int swdev_curve25519(wc_CryptoInfo* info)
info->pk.curve25519.outlen, info->pk.curve25519.endian);
}
#endif /* HAVE_CURVE25519_SHARED_SECRET */
static int swdev_curve25519_make_pub(wc_CryptoInfo* info)
{
return wc_curve25519_make_pub((int)info->pk.curve25519makepub.pubSz,
info->pk.curve25519makepub.pub,
(int)info->pk.curve25519makepub.privSz,
info->pk.curve25519makepub.priv);
}
static int swdev_curve25519_generic(wc_CryptoInfo* info)
{
return wc_curve25519_generic((int)info->pk.curve25519generic.pubSz,
info->pk.curve25519generic.pub,
(int)info->pk.curve25519generic.privSz,
info->pk.curve25519generic.priv,
(int)info->pk.curve25519generic.basepointSz,
info->pk.curve25519generic.basepoint);
}
#endif /* HAVE_CURVE25519 */
#ifndef NO_SHA256
@@ -992,6 +1010,10 @@ WC_SWDEV_EXPORT int wc_SwDev_Callback(int devId, wc_CryptoInfo* info,
case WC_PK_TYPE_CURVE25519:
return swdev_curve25519(info);
#endif
case WC_PK_TYPE_CURVE25519_MAKE_PUB:
return swdev_curve25519_make_pub(info);
case WC_PK_TYPE_CURVE25519_GENERIC:
return swdev_curve25519_generic(info);
#endif /* HAVE_CURVE25519 */
default:
return CRYPTOCB_UNAVAILABLE;
+63
View File
@@ -160,6 +160,8 @@ static const char* GetPkTypeStr(int pk)
case WC_PK_TYPE_EC_CHECK_PUB_KEY: return "ECC CheckPubKey";
case WC_PK_TYPE_ED25519_MAKE_PUB: return "ED25519 MakePub";
case WC_PK_TYPE_ED25519_CHECK_KEY: return "ED25519 CheckKey";
case WC_PK_TYPE_CURVE25519_MAKE_PUB: return "CURVE25519 MakePub";
case WC_PK_TYPE_CURVE25519_GENERIC: return "CURVE25519 Generic";
}
return NULL;
}
@@ -1142,6 +1144,67 @@ int wc_CryptoCb_Curve25519(curve25519_key* private_key,
return wc_CryptoCb_TranslateErrorCode(ret);
}
int wc_CryptoCb_Curve25519MakePub(int public_size, byte* pub,
int private_size, const byte* priv)
{
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
CryptoCb* dev;
if (pub == NULL || priv == NULL)
return ret;
/* try the find callback first, else grab the first registered device */
dev = wc_CryptoCb_FindDevice(INVALID_DEVID, WC_ALGO_TYPE_PK);
if (dev == NULL || dev->cb == NULL)
dev = wc_CryptoCb_FindDeviceByIndex(0);
if (dev && dev->cb) {
wc_CryptoInfo cryptoInfo;
XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
cryptoInfo.algo_type = WC_ALGO_TYPE_PK;
cryptoInfo.pk.type = WC_PK_TYPE_CURVE25519_MAKE_PUB;
cryptoInfo.pk.curve25519makepub.pub = pub;
cryptoInfo.pk.curve25519makepub.pubSz = (word32)public_size;
cryptoInfo.pk.curve25519makepub.priv = priv;
cryptoInfo.pk.curve25519makepub.privSz = (word32)private_size;
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
}
return wc_CryptoCb_TranslateErrorCode(ret);
}
int wc_CryptoCb_Curve25519Generic(int public_size, byte* pub,
int private_size, const byte* priv, int basepoint_size,
const byte* basepoint)
{
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
CryptoCb* dev;
if (pub == NULL || priv == NULL || basepoint == NULL)
return ret;
/* try the find callback first, else grab the first registered device */
dev = wc_CryptoCb_FindDevice(INVALID_DEVID, WC_ALGO_TYPE_PK);
if (dev == NULL || dev->cb == NULL)
dev = wc_CryptoCb_FindDeviceByIndex(0);
if (dev && dev->cb) {
wc_CryptoInfo cryptoInfo;
XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
cryptoInfo.algo_type = WC_ALGO_TYPE_PK;
cryptoInfo.pk.type = WC_PK_TYPE_CURVE25519_GENERIC;
cryptoInfo.pk.curve25519generic.pub = pub;
cryptoInfo.pk.curve25519generic.pubSz = (word32)public_size;
cryptoInfo.pk.curve25519generic.priv = priv;
cryptoInfo.pk.curve25519generic.privSz = (word32)private_size;
cryptoInfo.pk.curve25519generic.basepoint = basepoint;
cryptoInfo.pk.curve25519generic.basepointSz = (word32)basepoint_size;
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
}
return wc_CryptoCb_TranslateErrorCode(ret);
}
#endif /* HAVE_CURVE25519 */
#ifdef HAVE_ED25519
+66 -13
View File
@@ -86,10 +86,13 @@ const curve25519_set_type curve25519_sets[] = {
}
};
#if (!defined(WOLFSSL_CURVE25519_USE_ED25519) && \
/* base point is only referenced by the software scalar-mult paths, which are
* compiled out under WOLF_CRYPTO_CB_ONLY_CURVE25519 */
#if !defined(WOLF_CRYPTO_CB_ONLY_CURVE25519) && \
((!defined(WOLFSSL_CURVE25519_USE_ED25519) && \
!(defined(CURVED25519_X64) || (defined(WOLFSSL_ARMASM) && \
defined(__aarch64__)))) || defined(WOLFSSL_CURVE25519_BLINDING) || \
defined(WC_X25519_NONBLOCK)
defined(WC_X25519_NONBLOCK))
static const word32 kCurve25519BasePoint[CURVE25519_KEYSIZE/sizeof(word32)] = {
#ifdef BIG_ENDIAN_ORDER
0x09000000
@@ -147,7 +150,7 @@ int wc_curve25519_make_pub(int public_size, byte* pub, int private_size,
const byte* priv)
{
int ret;
#ifdef FREESCALE_LTC_ECC
#if defined(FREESCALE_LTC_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_CURVE25519)
const ECPoint* basepoint = nxp_ltc_curve25519_GetBasePoint();
ECPoint wc_pub;
#endif
@@ -165,6 +168,16 @@ int wc_curve25519_make_pub(int public_size, byte* pub, int private_size,
if (ret != 0)
return ret;
#ifdef WOLF_CRYPTO_CB
ret = wc_CryptoCb_Curve25519MakePub(public_size, pub, private_size, priv);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return ret;
/* fall-through when unavailable */
#endif
#ifdef WOLF_CRYPTO_CB_ONLY_CURVE25519
return NO_VALID_DEVID;
#else
#ifdef FREESCALE_LTC_ECC
/* input basepoint on Weierstrass curve */
ret = nxp_ltc_curve25519(&wc_pub, priv, basepoint, kLTC_Weierstrass);
@@ -229,6 +242,7 @@ int wc_curve25519_make_pub(int public_size, byte* pub, int private_size,
#endif
return ret;
#endif /* WOLF_CRYPTO_CB_ONLY_CURVE25519 */
}
#ifdef WOLFSSL_CURVE25519_BLINDING
@@ -236,6 +250,7 @@ int wc_curve25519_make_pub(int public_size, byte* pub, int private_size,
#ifndef WOLFSSL_CURVE25519_BLINDING_RAND_CNT
#define WOLFSSL_CURVE25519_BLINDING_RAND_CNT 10
#endif
#ifndef WOLF_CRYPTO_CB_ONLY_CURVE25519
static int curve25519_smul_blind(byte* rp, const byte* n, const byte* p,
WC_RNG* rng)
{
@@ -310,13 +325,14 @@ cleanup:
return ret;
}
#endif /* !WOLF_CRYPTO_CB_ONLY_CURVE25519 */
#endif
int wc_curve25519_make_pub_blind(int public_size, byte* pub, int private_size,
const byte* priv, WC_RNG* rng)
{
int ret;
#ifdef FREESCALE_LTC_ECC
#if defined(FREESCALE_LTC_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_CURVE25519)
const ECPoint* basepoint = nxp_ltc_curve25519_GetBasePoint();
ECPoint wc_pub;
#endif
@@ -339,6 +355,18 @@ int wc_curve25519_make_pub_blind(int public_size, byte* pub, int private_size,
if (ret != 0)
return ret;
#ifdef WOLF_CRYPTO_CB
ret = wc_CryptoCb_Curve25519MakePub(public_size, pub, private_size, priv);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return ret;
/* fall-through when unavailable */
#endif
#ifdef WOLF_CRYPTO_CB_ONLY_CURVE25519
/* the LTC path checks the rng, the callback path has no use for it */
(void)rng;
return NO_VALID_DEVID;
#else
#ifdef FREESCALE_LTC_ECC
/* input basepoint on Weierstrass curve */
ret = nxp_ltc_curve25519(&wc_pub, priv, basepoint, kLTC_Weierstrass);
@@ -358,6 +386,7 @@ int wc_curve25519_make_pub_blind(int public_size, byte* pub, int private_size,
}
return ret;
#endif /* WOLF_CRYPTO_CB_ONLY_CURVE25519 */
}
#endif
@@ -376,7 +405,6 @@ int wc_curve25519_generic(int public_size, byte* pub,
* nxp_ltc_curve25519_GetBasePoint() */
return WC_HW_E;
#else
#ifndef WOLFSSL_CURVE25519_BLINDING
int ret;
if ((public_size != CURVE25519_KEYSIZE) ||
@@ -392,6 +420,17 @@ int wc_curve25519_generic(int public_size, byte* pub,
if (ret != 0)
return ret;
#ifdef WOLF_CRYPTO_CB
ret = wc_CryptoCb_Curve25519Generic(public_size, pub, private_size, priv,
basepoint_size, basepoint);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return ret;
/* fall-through when unavailable */
#endif
#ifdef WOLF_CRYPTO_CB_ONLY_CURVE25519
return NO_VALID_DEVID;
#elif !defined(WOLFSSL_CURVE25519_BLINDING)
fe_init();
SAVE_VECTOR_REGISTERS(return _svr_ret;);
@@ -402,15 +441,16 @@ int wc_curve25519_generic(int public_size, byte* pub,
return ret;
#else
WC_RNG rng;
int ret;
{
WC_RNG rng;
ret = wc_InitRng(&rng);
if (ret == 0) {
ret = wc_curve25519_generic_blind(public_size, pub, private_size, priv,
basepoint_size, basepoint, &rng);
ret = wc_InitRng(&rng);
if (ret == 0) {
ret = wc_curve25519_generic_blind(public_size, pub, private_size,
priv, basepoint_size, basepoint, &rng);
wc_FreeRng(&rng);
wc_FreeRng(&rng);
}
}
return ret;
@@ -453,11 +493,23 @@ int wc_curve25519_generic_blind(int public_size, byte* pub,
if (ret != 0)
return ret;
#ifdef WOLF_CRYPTO_CB
ret = wc_CryptoCb_Curve25519Generic(public_size, pub, private_size, priv,
basepoint_size, basepoint);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return ret;
/* fall-through when unavailable */
#endif
#ifdef WOLF_CRYPTO_CB_ONLY_CURVE25519
return NO_VALID_DEVID;
#else
fe_init();
ret = curve25519_smul_blind(pub, priv, basepoint, rng);
return ret;
#endif /* WOLF_CRYPTO_CB_ONLY_CURVE25519 */
#endif /* FREESCALE_LTC_ECC */
}
#endif
@@ -1233,7 +1285,8 @@ int wc_curve25519_init_ex(curve25519_key* key, void* heap, int devId)
#endif
(void)heap; /* if needed for XMALLOC/XFREE in future */
#ifndef FREESCALE_LTC_ECC
/* field math is implemented in the callback in crypto cb only */
#if !defined(FREESCALE_LTC_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_CURVE25519)
fe_init();
#endif
+4 -3
View File
@@ -23,9 +23,10 @@
/* Based from Daniel Beer's public domain work. */
/* under WOLF_CRYPTO_CB_ONLY_ED25519 the callback device does all Ed25519
* field math, so Ed25519 alone no longer pulls this file in */
#if defined(HAVE_CURVE25519) || \
/* under WOLF_CRYPTO_CB_ONLY_ED25519 / WOLF_CRYPTO_CB_ONLY_CURVE25519 the
* callback device does all the field math, so neither algorithm pulls this
* file in on its own */
#if (defined(HAVE_CURVE25519) && !defined(WOLF_CRYPTO_CB_ONLY_CURVE25519)) || \
(defined(HAVE_ED25519) && !defined(WOLF_CRYPTO_CB_ONLY_ED25519))
#if defined(CURVE25519_SMALL) || defined(ED25519_SMALL) /* use slower code that takes less memory */
+1 -3
View File
@@ -23,9 +23,7 @@
/* Based On Daniel J Bernstein's curve25519 Public Domain ref10 work. */
/* under WOLF_CRYPTO_CB_ONLY_ED25519 the callback device does all Ed25519
* field math, so Ed25519 alone no longer pulls this file in */
#if defined(HAVE_CURVE25519) || \
#if (defined(HAVE_CURVE25519) && !defined(WOLF_CRYPTO_CB_ONLY_CURVE25519)) || \
(defined(HAVE_ED25519) && !defined(WOLF_CRYPTO_CB_ONLY_ED25519))
#if !defined(CURVE25519_SMALL) && !defined(ED25519_SMALL)
+2 -1
View File
@@ -30,7 +30,8 @@
* group math, so this file (and its large precomputed tables) compiles out
* unless curve25519 also needs it */
#if (defined(HAVE_ED25519) && !defined(WOLF_CRYPTO_CB_ONLY_ED25519)) || \
defined(WOLFSSL_CURVE25519_USE_ED25519)
(defined(WOLFSSL_CURVE25519_USE_ED25519) && \
!defined(WOLF_CRYPTO_CB_ONLY_CURVE25519))
#ifndef ED25519_SMALL /* run when not defined to use small memory math */
#include <wolfssl/wolfcrypt/ed25519.h>
+21
View File
@@ -303,6 +303,20 @@ typedef struct wc_CryptoInfo {
word32* outlen;
int endian;
} curve25519;
struct {
byte* pub;
word32 pubSz;
const byte* priv;
word32 privSz;
} curve25519makepub;
struct {
byte* pub;
word32 pubSz;
const byte* priv;
word32 privSz;
const byte* basepoint;
word32 basepointSz;
} curve25519generic;
#endif
#ifdef HAVE_ED25519
struct {
@@ -847,6 +861,13 @@ WOLFSSL_LOCAL int wc_CryptoCb_Curve25519Gen(WC_RNG* rng, int keySize,
WOLFSSL_LOCAL int wc_CryptoCb_Curve25519(curve25519_key* private_key,
curve25519_key* public_key, byte* out, word32* outlen, int endian);
WOLFSSL_LOCAL int wc_CryptoCb_Curve25519MakePub(int public_size, byte* pub,
int private_size, const byte* priv);
WOLFSSL_LOCAL int wc_CryptoCb_Curve25519Generic(int public_size, byte* pub,
int private_size, const byte* priv, int basepoint_size,
const byte* basepoint);
#endif /* HAVE_CURVE25519 */
#ifdef HAVE_ED25519
+4
View File
@@ -1631,6 +1631,10 @@ enum wc_PkType {
#undef _WC_PK_TYPE_MAX
#define _WC_PK_TYPE_MAX WC_PK_TYPE_ECIES_DECRYPT
#endif
WC_PK_TYPE_CURVE25519_MAKE_PUB = 40,
WC_PK_TYPE_CURVE25519_GENERIC = 41,
#undef _WC_PK_TYPE_MAX
#define _WC_PK_TYPE_MAX WC_PK_TYPE_CURVE25519_GENERIC
WC_PK_TYPE_MAX = _WC_PK_TYPE_MAX
};