From 1c9efc4310f9a3207e09088f48f5e13323f3ed2b Mon Sep 17 00:00:00 2001 From: Yosuke Shimizu Date: Wed, 12 Aug 2026 16:21:07 +0900 Subject: [PATCH] Reject curve448 public key export from an unset key --- doc/dox_comments/header_files-ja/curve448.h | 6 ++++-- doc/dox_comments/header_files/curve448.h | 6 ++++-- tests/api/test_curve448.c | 19 +++++++++++++++++++ wolfcrypt/src/curve448.c | 11 +++++++++-- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/doc/dox_comments/header_files-ja/curve448.h b/doc/dox_comments/header_files-ja/curve448.h index 08a3d451728..9dad87e5c44 100644 --- a/doc/dox_comments/header_files-ja/curve448.h +++ b/doc/dox_comments/header_files-ja/curve448.h @@ -509,7 +509,8 @@ int wc_curve448_check_public(const byte* pub, word32 pubSz, int endian); \brief この関数は、与えられた鍵構造体から公開鍵をエクスポートし、結果をoutバッファに格納します。ビッグエンディアンのみ。 \return 0 curve448_key構造体から公開鍵のエクスポートに成功した場合に返されます。 - \return ECC_BAD_ARG_E outLenがCURVE448_PUB_KEY_SIZEより小さい場合に返されます。 + \return ECC_BAD_ARG_E outLenがCURVE448_PUB_KEY_SIZEより小さい場合、 + または公開鍵と秘密鍵のどちらも設定されていない場合に返されます。 \return BAD_FUNC_ARG 入力パラメータのいずれかがNULLの場合に返されます。 \param [in] key 鍵をエクスポートするcurve448_key構造体へのポインタ。 @@ -546,7 +547,8 @@ int wc_curve448_export_public(curve448_key* key, byte* out, word32* outLen); \brief この関数は、与えられた鍵構造体から公開鍵をエクスポートし、結果をoutバッファに格納します。ビッグエンディアンとリトルエンディアンの両方をサポートします。 \return 0 curve448_key構造体から公開鍵のエクスポートに成功した場合に返されます。 - \return ECC_BAD_ARG_E outLenがCURVE448_PUB_KEY_SIZEより小さい場合に返されます。 + \return ECC_BAD_ARG_E outLenがCURVE448_PUB_KEY_SIZEより小さい場合、 + または公開鍵と秘密鍵のどちらも設定されていない場合に返されます。 \return BAD_FUNC_ARG 入力パラメータのいずれかがNULLの場合に返されます。 \param [in] key 鍵をエクスポートするcurve448_key構造体へのポインタ。 diff --git a/doc/dox_comments/header_files/curve448.h b/doc/dox_comments/header_files/curve448.h index 23ff7253c2e..aaa984a356b 100644 --- a/doc/dox_comments/header_files/curve448.h +++ b/doc/dox_comments/header_files/curve448.h @@ -565,7 +565,8 @@ int wc_curve448_check_public(const byte* pub, word32 pubSz, int endian); \return 0 Returned on successfully exporting the public key from the curve448_key structure. - \return ECC_BAD_ARG_E Returned if outLen is less than CURVE448_PUB_KEY_SIZE. + \return ECC_BAD_ARG_E Returned if outLen is less than CURVE448_PUB_KEY_SIZE, + or if neither the public nor the private key has been set. \return BAD_FUNC_ARG Returned if any of the input parameters are NULL. \param [in] key Pointer to the curve448_key structure in from which to @@ -605,7 +606,8 @@ int wc_curve448_export_public(curve448_key* key, byte* out, word32* outLen); \return 0 Returned on successfully exporting the public key from the curve448_key structure. - \return ECC_BAD_ARG_E Returned if outLen is less than CURVE448_PUB_KEY_SIZE. + \return ECC_BAD_ARG_E Returned if outLen is less than CURVE448_PUB_KEY_SIZE, + or if neither the public nor the private key has been set. \return BAD_FUNC_ARG Returned if any of the input parameters are NULL. \param [in] key Pointer to the curve448_key structure in from which to diff --git a/tests/api/test_curve448.c b/tests/api/test_curve448.c index 83f9e48a042..38a4be46713 100644 --- a/tests/api/test_curve448.c +++ b/tests/api/test_curve448.c @@ -167,18 +167,30 @@ int test_wc_curve448_export_public_ex(void) #if defined(HAVE_CURVE448) WC_RNG rng; curve448_key key; + curve448_key unset; + curve448_key pubOnly; byte out[CURVE448_KEY_SIZE]; + byte pubOut[CURVE448_KEY_SIZE]; word32 outLen = sizeof(out); + word32 pubOutLen = sizeof(pubOut); int endian = EC448_BIG_ENDIAN; XMEMSET(&rng, 0, sizeof(WC_RNG)); ExpectIntEQ(wc_curve448_init(&key), 0); + ExpectIntEQ(wc_curve448_init(&unset), 0); + ExpectIntEQ(wc_curve448_init(&pubOnly), 0); ExpectIntEQ(wc_InitRng(&rng), 0); ExpectIntEQ(wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &key), 0); ExpectIntEQ(wc_curve448_export_public(&key, out, &outLen), 0); ExpectIntEQ(wc_curve448_export_public_ex(&key, out, &outLen, endian), 0); + /* a key holding only a public component exports it unchanged */ + ExpectIntEQ(wc_curve448_import_public(out, outLen, &pubOnly), 0); + ExpectIntEQ(wc_curve448_export_public_ex(&pubOnly, pubOut, &pubOutLen, + endian), 0); + ExpectIntEQ(pubOutLen, CURVE448_PUB_KEY_SIZE); + ExpectIntEQ(XMEMCMP(out, pubOut, CURVE448_PUB_KEY_SIZE), 0); /* test bad cases */ ExpectIntEQ(wc_curve448_export_public_ex(NULL, NULL, NULL, endian), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); @@ -188,12 +200,19 @@ int test_wc_curve448_export_public_ex(void) WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_curve448_export_public_ex(&key, out, NULL, endian), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* no private or public key set to export */ + ExpectIntEQ(wc_curve448_export_public(&unset, out, &outLen), + WC_NO_ERR_TRACE(ECC_BAD_ARG_E)); + ExpectIntEQ(wc_curve448_export_public_ex(&unset, out, &outLen, endian), + WC_NO_ERR_TRACE(ECC_BAD_ARG_E)); outLen = outLen - 2; ExpectIntEQ(wc_curve448_export_public_ex(&key, out, &outLen, endian), WC_NO_ERR_TRACE(ECC_BAD_ARG_E)); DoExpectIntEQ(wc_FreeRng(&rng), 0); wc_curve448_free(&key); + wc_curve448_free(&unset); + wc_curve448_free(&pubOnly); #endif return EXPECT_RESULT(); } /* END test_wc_curve448_export_public_ex */ diff --git a/wolfcrypt/src/curve448.c b/wolfcrypt/src/curve448.c index cce2e1beb00..e2448ba423b 100644 --- a/wolfcrypt/src/curve448.c +++ b/wolfcrypt/src/curve448.c @@ -232,7 +232,8 @@ int wc_curve448_shared_secret_ex(curve448_key* private_key, * outLen [in/out] On in, the number of bytes in array. * On out, the number bytes put into array. * returns BAD_FUNC_ARG when a parameter is NULL, - * ECC_BAD_ARG_E when outLen is less than CURVE448_PUB_KEY_SIZE, + * ECC_BAD_ARG_E when outLen is less than CURVE448_PUB_KEY_SIZE or + * neither the public nor the private key has been set, * 0 otherwise. */ int wc_curve448_export_public(curve448_key* key, byte* out, word32* outLen) @@ -248,7 +249,8 @@ int wc_curve448_export_public(curve448_key* key, byte* out, word32* outLen) * On out, the number bytes put into array. * endian [in] Endianness to use when encoding number in array. * returns BAD_FUNC_ARG when a parameter is NULL, - * ECC_BAD_ARG_E when outLen is less than CURVE448_PUB_KEY_SIZE, + * ECC_BAD_ARG_E when outLen is less than CURVE448_PUB_KEY_SIZE or + * neither the public nor the private key has been set, * 0 otherwise. */ int wc_curve448_export_public_ex(curve448_key* key, byte* out, word32* outLen, @@ -265,6 +267,11 @@ int wc_curve448_export_public_ex(curve448_key* key, byte* out, word32* outLen, *outLen = CURVE448_PUB_KEY_SIZE; ret = ECC_BAD_ARG_E; } + + /* no public key to export and no private key to derive it from */ + if ((ret == 0) && (!key->pubSet) && (!key->privSet)) { + ret = ECC_BAD_ARG_E; + } if (ret == 0) { /* calculate public if missing */ if (!key->pubSet) {