Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/wh_client_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -3404,6 +3404,11 @@ int wh_Client_Curve25519MakeCacheKey(whClientContext* ctx, uint16_t size,
return WH_ERROR_BADARGS;
}

/* Ephemeral keygen belongs to the export path, not the cache path. */
if (flags & WH_NVM_FLAGS_EPHEMERAL) {
return WH_ERROR_BADARGS;
}
Comment on lines +3408 to +3410

return _Curve25519MakeKey(ctx, size, inout_key_id, flags, label, label_len,
NULL);
}
Expand Down Expand Up @@ -3920,6 +3925,11 @@ int wh_Client_Ed25519MakeCacheKey(whClientContext* ctx, whKeyId* inout_key_id,
return WH_ERROR_BADARGS;
}

/* Ephemeral keygen belongs to the export path, not the cache path. */
if (flags & WH_NVM_FLAGS_EPHEMERAL) {
return WH_ERROR_BADARGS;
}

return _Ed25519MakeKey(ctx, inout_key_id, flags, label_len, label, NULL);
}

Expand Down Expand Up @@ -10324,6 +10334,11 @@ int wh_Client_MlDsaMakeCacheKey(whClientContext* ctx, int size, int level,
return WH_ERROR_BADARGS;
}

/* Ephemeral keygen belongs to the export path, not the cache path. */
if (flags & WH_NVM_FLAGS_EPHEMERAL) {
return WH_ERROR_BADARGS;
}

return _MlDsaMakeKey(ctx, size, level, inout_key_id, flags, label_len,
label, NULL);
}
Expand Down Expand Up @@ -11503,6 +11518,11 @@ int wh_Client_MlKemMakeCacheKey(whClientContext* ctx, int level,
return WH_ERROR_BADARGS;
}

/* Ephemeral keygen belongs to the export path, not the cache path. */
if (flags & WH_NVM_FLAGS_EPHEMERAL) {
return WH_ERROR_BADARGS;
}

return _MlKemMakeKey(ctx, level, inout_key_id, flags, label_len,
label, NULL);
}
Expand Down
19 changes: 19 additions & 0 deletions test-refactor/client-server/wh_test_crypto_curve25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,11 +467,30 @@ static int _whTest_CryptoCurve25519CacheKeyAndExportPublic(whClientContext* ctx)
return ret;
}

/* Cache keygen must reject WH_NVM_FLAGS_EPHEMERAL */
static int _whTest_CryptoCurve25519MakeCacheKeyEphemeral(whClientContext* ctx)
{
whKeyId keyId = WH_KEYID_ERASED;
int ret;

ret = wh_Client_Curve25519MakeCacheKey(ctx, CURVE25519_KEYSIZE, &keyId,
WH_NVM_FLAGS_EPHEMERAL, NULL, 0);
if (ret != WH_ERROR_BADARGS) {
WH_ERROR_PRINT("Curve25519MakeCacheKey with EPHEMERAL returned %d "
"(expected BADARGS)\n",
ret);
return WH_TEST_FAIL;
}
WH_TEST_PRINT("CURVE25519 CACHE-KEY EPHEMERAL REJECT SUCCESS\n");
return 0;
}

int whTest_Crypto_Curve25519(whClientContext* ctx)
{
WH_TEST_RETURN_ON_FAIL(_whTest_CryptoCurve25519(ctx));
WH_TEST_RETURN_ON_FAIL(_whTest_CryptoCurve25519ExportPublicKey(ctx));
WH_TEST_RETURN_ON_FAIL(_whTest_CryptoCurve25519CacheKeyAndExportPublic(ctx));
WH_TEST_RETURN_ON_FAIL(_whTest_CryptoCurve25519MakeCacheKeyEphemeral(ctx));
return 0;
}
#endif /* HAVE_CURVE25519 */
Expand Down
19 changes: 19 additions & 0 deletions test-refactor/client-server/wh_test_crypto_ed25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,24 @@ static int _whTest_CryptoEd25519BufferTooSmall(whClientContext* ctx)
return ret;
}

/* Cache keygen must reject WH_NVM_FLAGS_EPHEMERAL */
static int _whTest_CryptoEd25519MakeCacheKeyEphemeral(whClientContext* ctx)
{
whKeyId keyId = WH_KEYID_ERASED;
int ret;

ret = wh_Client_Ed25519MakeCacheKey(ctx, &keyId, WH_NVM_FLAGS_EPHEMERAL, 0,
NULL);
if (ret != WH_ERROR_BADARGS) {
WH_ERROR_PRINT("Ed25519MakeCacheKey with EPHEMERAL returned %d "
"(expected BADARGS)\n",
ret);
return WH_TEST_FAIL;
}
WH_TEST_PRINT("Ed25519 CACHE-KEY EPHEMERAL REJECT SUCCESS\n");
return 0;
}

int whTest_Crypto_Ed25519(whClientContext* ctx)
{
WH_TEST_RETURN_ON_FAIL(_whTest_CryptoEd25519Inline(ctx));
Expand All @@ -737,6 +755,7 @@ int whTest_Crypto_Ed25519(whClientContext* ctx)
WH_TEST_RETURN_ON_FAIL(_whTest_CryptoEd25519ExportPublicKey(ctx));
WH_TEST_RETURN_ON_FAIL(_whTest_CryptoEd25519CacheKeyAndExportPublic(ctx));
WH_TEST_RETURN_ON_FAIL(_whTest_CryptoEd25519BufferTooSmall(ctx));
WH_TEST_RETURN_ON_FAIL(_whTest_CryptoEd25519MakeCacheKeyEphemeral(ctx));
return 0;
}
#endif /* HAVE_ED25519 */
Expand Down
19 changes: 19 additions & 0 deletions test-refactor/client-server/wh_test_crypto_mldsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -1319,6 +1319,24 @@ static int _whTest_CryptoMlDsaBufferTooSmall(whClientContext* ctx)
wc_MlDsaKey_Free(key);
return ret;
}

/* Cache keygen must reject WH_NVM_FLAGS_EPHEMERAL */
static int _whTest_CryptoMlDsaMakeCacheKeyEphemeral(whClientContext* ctx)
{
whKeyId keyId = WH_KEYID_ERASED;
int ret;

ret = wh_Client_MlDsaMakeCacheKey(ctx, 0, WC_ML_DSA_44, &keyId,
WH_NVM_FLAGS_EPHEMERAL, 0, NULL);
if (ret != WH_ERROR_BADARGS) {
WH_ERROR_PRINT("MlDsaMakeCacheKey with EPHEMERAL returned %d "
"(expected BADARGS)\n",
ret);
return WH_TEST_FAIL;
}
WH_TEST_PRINT("ML-DSA CACHE-KEY EPHEMERAL REJECT SUCCESS\n");
return 0;
}
#endif /* make/sign/verify && ML_DSA_44 */

int whTest_Crypto_MlDsa(whClientContext* ctx)
Expand All @@ -1345,6 +1363,7 @@ int whTest_Crypto_MlDsa(whClientContext* ctx)
WH_TEST_RETURN_ON_FAIL(_whTest_CryptoMlDsaCacheKeyAndExportPublic(ctx));
#endif
WH_TEST_RETURN_ON_FAIL(_whTest_CryptoMlDsaBufferTooSmall(ctx));
WH_TEST_RETURN_ON_FAIL(_whTest_CryptoMlDsaMakeCacheKeyEphemeral(ctx));
#ifdef WOLFHSM_CFG_DMA
WH_TEST_RETURN_ON_FAIL(_whTest_CryptoMlDsaDmaClient(ctx));
WH_TEST_RETURN_ON_FAIL(_whTest_CryptoMlDsaExportPublicKeyDma(ctx));
Expand Down
82 changes: 82 additions & 0 deletions test-refactor/client-server/wh_test_crypto_mlkem.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright (C) 2026 wolfSSL Inc.
*
* This file is part of wolfHSM.
*
* wolfHSM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfHSM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with wolfHSM. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* test-refactor/client-server/wh_test_crypto_mlkem.c
*
* ML-KEM tests routed through the server:
* _whTest_CryptoMlKemMakeCacheKeyEphemeral - cache keygen rejects
* WH_NVM_FLAGS_EPHEMERAL
*/

#include "wolfhsm/wh_settings.h"

#if !defined(WOLFHSM_CFG_NO_CRYPTO)

#include <stdint.h>

#include "wolfssl/wolfcrypt/settings.h"
#include "wolfssl/wolfcrypt/types.h"
#include "wolfssl/wolfcrypt/wc_mlkem.h"

#include "wolfhsm/wh_error.h"
#include "wolfhsm/wh_common.h"
#include "wolfhsm/wh_client.h"
#include "wolfhsm/wh_client_crypto.h"

#include "wh_test_common.h"
#include "wh_test_list.h"

#ifdef WOLFSSL_HAVE_MLKEM

/* Cache keygen must reject WH_NVM_FLAGS_EPHEMERAL */
static int _whTest_CryptoMlKemMakeCacheKeyEphemeral(whClientContext* ctx)
{
whKeyId keyId = WH_KEYID_ERASED;
int ret;
/* Valid level so the server level check cannot mask the gate */
const int level =
#if !defined(WOLFSSL_NO_ML_KEM_512)
WC_ML_KEM_512;
#elif !defined(WOLFSSL_NO_ML_KEM_768)
WC_ML_KEM_768;
#else
WC_ML_KEM_1024;
#endif

ret = wh_Client_MlKemMakeCacheKey(ctx, level, &keyId,
WH_NVM_FLAGS_EPHEMERAL, 0, NULL);
if (ret != WH_ERROR_BADARGS) {
WH_ERROR_PRINT("MlKemMakeCacheKey with EPHEMERAL returned %d "
"(expected BADARGS)\n",
ret);
return WH_TEST_FAIL;
}
WH_TEST_PRINT("ML-KEM CACHE-KEY EPHEMERAL REJECT SUCCESS\n");
return 0;
}

int whTest_Crypto_MlKem(whClientContext* ctx)
{
WH_TEST_RETURN_ON_FAIL(_whTest_CryptoMlKemMakeCacheKeyEphemeral(ctx));
return 0;
}

#endif /* WOLFSSL_HAVE_MLKEM */

#endif /* !WOLFHSM_CFG_NO_CRYPTO */
2 changes: 2 additions & 0 deletions test-refactor/wh_test_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ WH_TEST_DECL(whTest_Crypto_KeyWrap);
WH_TEST_DECL(whTest_Crypto_Keystore);
WH_TEST_DECL(whTest_Crypto_Lms);
WH_TEST_DECL(whTest_Crypto_MlDsa);
WH_TEST_DECL(whTest_Crypto_MlKem);
WH_TEST_DECL(whTest_Crypto_Rng);
WH_TEST_DECL(whTest_Crypto_Rsa);
WH_TEST_DECL(whTest_Crypto_Sha);
Expand Down Expand Up @@ -161,6 +162,7 @@ const whTestCase whTestsClient[] = {
{"whTest_Crypto_Keystore", whTest_Crypto_Keystore},
{"whTest_Crypto_Lms", whTest_Crypto_Lms},
{"whTest_Crypto_MlDsa", whTest_Crypto_MlDsa},
{"whTest_Crypto_MlKem", whTest_Crypto_MlKem},
{"whTest_Crypto_Rng", whTest_Crypto_Rng},
{"whTest_Crypto_Rsa", whTest_Crypto_Rsa},
{"whTest_Crypto_Sha", whTest_Crypto_Sha},
Expand Down
49 changes: 38 additions & 11 deletions test/wh_test_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -17958,10 +17958,7 @@ int whTest_CryptoKeyRevocationAesCbc(whClientContext* client, WC_RNG* rng)
#endif /* !NO_AES && HAVE_AES_CBC && \
WOLFHSM_CFG_TEST_ALLOW_PERSISTENT_NVM_ARTIFACTS */

/* Negative tests: every cache-and-export keygen function must reject
* WH_NVM_FLAGS_EPHEMERAL, a NULL inout_key_id, and a NULL pub with
* WH_ERROR_BADARGS, before contacting the server. level is passed as 0 for the
* PQC calls since the argument guards run before any level validation. */
/* Cache keygen must reject EPHEMERAL flags and NULL args with BADARGS */
static int whTest_CryptoMakeCacheKeyExportPublicArgs(whClientContext* ctx)
{
int ret = 0;
Expand Down Expand Up @@ -18010,9 +18007,12 @@ static int whTest_CryptoMakeCacheKeyExportPublicArgs(whClientContext* ctx)
#ifdef HAVE_CURVE25519
if (ret == 0) {
curve25519_key cv[1] = {0};
if (wh_Client_Curve25519MakeCacheKeyAndExportPublic(
ctx, CURVE25519_KEYSIZE, &keyId, WH_NVM_FLAGS_EPHEMERAL, NULL, 0,
cv) != WH_ERROR_BADARGS ||
if (wh_Client_Curve25519MakeCacheKey(ctx, CURVE25519_KEYSIZE, &keyId,
WH_NVM_FLAGS_EPHEMERAL, NULL,
0) != WH_ERROR_BADARGS ||
wh_Client_Curve25519MakeCacheKeyAndExportPublic(
ctx, CURVE25519_KEYSIZE, &keyId, WH_NVM_FLAGS_EPHEMERAL, NULL,
0, cv) != WH_ERROR_BADARGS ||
wh_Client_Curve25519MakeCacheKeyAndExportPublic(
ctx, CURVE25519_KEYSIZE, NULL, WH_NVM_FLAGS_NONE, NULL, 0,
cv) != WH_ERROR_BADARGS ||
Expand All @@ -18027,11 +18027,14 @@ static int whTest_CryptoMakeCacheKeyExportPublicArgs(whClientContext* ctx)
#ifdef HAVE_ED25519
if (ret == 0) {
ed25519_key ed[1] = {0};
if (wh_Client_Ed25519MakeCacheKeyAndExportPublic(
if (wh_Client_Ed25519MakeCacheKey(ctx, &keyId, WH_NVM_FLAGS_EPHEMERAL,
0, NULL) != WH_ERROR_BADARGS ||
wh_Client_Ed25519MakeCacheKeyAndExportPublic(
ctx, &keyId, WH_NVM_FLAGS_EPHEMERAL, 0, NULL, ed) !=
WH_ERROR_BADARGS ||
wh_Client_Ed25519MakeCacheKeyAndExportPublic(
ctx, NULL, WH_NVM_FLAGS_NONE, 0, NULL, ed) != WH_ERROR_BADARGS ||
ctx, NULL, WH_NVM_FLAGS_NONE, 0, NULL, ed) !=
WH_ERROR_BADARGS ||
wh_Client_Ed25519MakeCacheKeyAndExportPublic(
ctx, &keyId, WH_NVM_FLAGS_NONE, 0, NULL, NULL) !=
WH_ERROR_BADARGS) {
Expand All @@ -18043,7 +18046,19 @@ static int whTest_CryptoMakeCacheKeyExportPublicArgs(whClientContext* ctx)
#ifdef WOLFSSL_MLDSA_PUBLIC_KEY
if (ret == 0) {
wc_MlDsaKey mldsa[1] = {0};
if (wh_Client_MlDsaMakeCacheKeyAndExportPublic(
/* Valid level so the server level check cannot mask the gate */
const int mldsaLevel =
#if !defined(WOLFSSL_NO_ML_DSA_44)
WC_ML_DSA_44;
#elif !defined(WOLFSSL_NO_ML_DSA_65)
WC_ML_DSA_65;
#else
WC_ML_DSA_87;
#endif
if (wh_Client_MlDsaMakeCacheKey(ctx, 0, mldsaLevel, &keyId,
WH_NVM_FLAGS_EPHEMERAL, 0,
NULL) != WH_ERROR_BADARGS ||
wh_Client_MlDsaMakeCacheKeyAndExportPublic(
ctx, 0, 0, &keyId, WH_NVM_FLAGS_EPHEMERAL, 0, NULL, mldsa) !=
WH_ERROR_BADARGS ||
wh_Client_MlDsaMakeCacheKeyAndExportPublic(
Expand Down Expand Up @@ -18075,7 +18090,19 @@ static int whTest_CryptoMakeCacheKeyExportPublicArgs(whClientContext* ctx)
#ifdef WOLFSSL_HAVE_MLKEM
if (ret == 0) {
MlKemKey mlkem[1] = {0};
if (wh_Client_MlKemMakeCacheKeyAndExportPublic(
/* Valid level so the server level check cannot mask the gate */
const int mlkemLevel =
#if !defined(WOLFSSL_NO_ML_KEM_512)
WC_ML_KEM_512;
#elif !defined(WOLFSSL_NO_ML_KEM_768)
WC_ML_KEM_768;
#else
WC_ML_KEM_1024;
#endif
if (wh_Client_MlKemMakeCacheKey(ctx, mlkemLevel, &keyId,
WH_NVM_FLAGS_EPHEMERAL, 0,
NULL) != WH_ERROR_BADARGS ||
wh_Client_MlKemMakeCacheKeyAndExportPublic(
ctx, 0, &keyId, WH_NVM_FLAGS_EPHEMERAL, 0, NULL, mlkem) !=
WH_ERROR_BADARGS ||
wh_Client_MlKemMakeCacheKeyAndExportPublic(
Expand Down
Loading