Skip to content
Merged
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
46 changes: 46 additions & 0 deletions tests/api/test_ed25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,52 @@ int test_wc_ed25519_sign_msg(void)

} /* END test_wc_ed25519_sign_msg */

/*
* Test that wc_ed25519_sign_msg() rejects a public-key-only key object.
* A key with pubKeySet=1 but privKeySet=0 must not silently sign.
*/
int test_wc_ed25519_sign_msg_pubonly_fails(void)
{
EXPECT_DECLS;
#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)
#if defined(HAVE_ED25519) && defined(HAVE_ED25519_SIGN) && \
defined(HAVE_ED25519_KEY_IMPORT) && defined(HAVE_ED25519_KEY_EXPORT)
ed25519_key fullKey;
ed25519_key pubOnlyKey;
WC_RNG rng;
byte pubBuf[ED25519_PUB_KEY_SIZE];
word32 pubSz = sizeof(pubBuf);
byte msg[] = "test message for pubonly check";
byte sig[ED25519_SIG_SIZE];
word32 sigLen = sizeof(sig);

XMEMSET(&fullKey, 0, sizeof(fullKey));
XMEMSET(&pubOnlyKey, 0, sizeof(pubOnlyKey));
XMEMSET(&rng, 0, sizeof(rng));

ExpectIntEQ(wc_ed25519_init(&fullKey), 0);
ExpectIntEQ(wc_ed25519_init(&pubOnlyKey), 0);
ExpectIntEQ(wc_InitRng(&rng), 0);

/* Generate a real key pair and export its public key. */
ExpectIntEQ(wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &fullKey), 0);
ExpectIntEQ(wc_ed25519_export_public(&fullKey, pubBuf, &pubSz), 0);

/* Import only the public key into a fresh key object. */
ExpectIntEQ(wc_ed25519_import_public(pubBuf, pubSz, &pubOnlyKey), 0);

/* Signing with a public-key-only object must fail. */
ExpectIntEQ(wc_ed25519_sign_msg(msg, sizeof(msg), sig, &sigLen,
&pubOnlyKey), WC_NO_ERR_TRACE(BAD_FUNC_ARG));

DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_ed25519_free(&pubOnlyKey);
wc_ed25519_free(&fullKey);
#endif
#endif
return EXPECT_RESULT();
} /* END test_wc_ed25519_sign_msg_pubonly_fails */

/*
* Testing wc_ed25519_import_public()
*/
Expand Down
2 changes: 2 additions & 0 deletions tests/api/test_ed25519.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
int test_wc_ed25519_make_key(void);
int test_wc_ed25519_init(void);
int test_wc_ed25519_sign_msg(void);
int test_wc_ed25519_sign_msg_pubonly_fails(void);
int test_wc_ed25519_import_public(void);
int test_wc_ed25519_import_private_key(void);
int test_wc_ed25519_export(void);
Expand All @@ -40,6 +41,7 @@ int test_wc_Ed25519PrivateKeyToDer(void);
TEST_DECL_GROUP("ed25519", test_wc_ed25519_make_key), \
TEST_DECL_GROUP("ed25519", test_wc_ed25519_init), \
TEST_DECL_GROUP("ed25519", test_wc_ed25519_sign_msg), \
TEST_DECL_GROUP("ed25519", test_wc_ed25519_sign_msg_pubonly_fails), \
TEST_DECL_GROUP("ed25519", test_wc_ed25519_import_public), \
TEST_DECL_GROUP("ed25519", test_wc_ed25519_import_private_key), \
TEST_DECL_GROUP("ed25519", test_wc_ed25519_export), \
Expand Down
46 changes: 46 additions & 0 deletions tests/api/test_ed448.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,52 @@ int test_wc_ed448_sign_msg(void)
return EXPECT_RESULT();
} /* END test_wc_ed448_sign_msg */

/*
* Test that wc_ed448_sign_msg() rejects a public-key-only key object.
* A key with pubKeySet=1 but privKeySet=0 must not silently sign.
*/
int test_wc_ed448_sign_msg_pubonly_fails(void)
{
EXPECT_DECLS;
#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)
#if defined(HAVE_ED448) && defined(HAVE_ED448_SIGN) && \
defined(HAVE_ED448_KEY_IMPORT) && defined(HAVE_ED448_KEY_EXPORT)
ed448_key fullKey;
ed448_key pubOnlyKey;
WC_RNG rng;
byte pubBuf[ED448_PUB_KEY_SIZE];
word32 pubSz = sizeof(pubBuf);
byte msg[] = "test message for pubonly check";
byte sig[ED448_SIG_SIZE];
word32 sigLen = sizeof(sig);

XMEMSET(&fullKey, 0, sizeof(fullKey));
XMEMSET(&pubOnlyKey, 0, sizeof(pubOnlyKey));
XMEMSET(&rng, 0, sizeof(rng));

ExpectIntEQ(wc_ed448_init(&fullKey), 0);
ExpectIntEQ(wc_ed448_init(&pubOnlyKey), 0);
ExpectIntEQ(wc_InitRng(&rng), 0);

/* Generate a real key pair and export its public key. */
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &fullKey), 0);
ExpectIntEQ(wc_ed448_export_public(&fullKey, pubBuf, &pubSz), 0);

/* Import only the public key into a fresh key object. */
ExpectIntEQ(wc_ed448_import_public(pubBuf, pubSz, &pubOnlyKey), 0);

/* Signing with a public-key-only object must fail. */
ExpectIntEQ(wc_ed448_sign_msg(msg, sizeof(msg), sig, &sigLen,
&pubOnlyKey, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG));

DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_ed448_free(&pubOnlyKey);
wc_ed448_free(&fullKey);
#endif
#endif
return EXPECT_RESULT();
} /* END test_wc_ed448_sign_msg_pubonly_fails */

/*
* Testing wc_ed448_import_public()
*/
Expand Down
2 changes: 2 additions & 0 deletions tests/api/test_ed448.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
int test_wc_ed448_make_key(void);
int test_wc_ed448_init(void);
int test_wc_ed448_sign_msg(void);
int test_wc_ed448_sign_msg_pubonly_fails(void);
int test_wc_ed448_import_public(void);
int test_wc_ed448_import_private_key(void);
int test_wc_ed448_export(void);
Expand All @@ -40,6 +41,7 @@ int test_wc_Ed448PrivateKeyToDer(void);
TEST_DECL_GROUP("ed448", test_wc_ed448_make_key), \
TEST_DECL_GROUP("ed448", test_wc_ed448_init), \
TEST_DECL_GROUP("ed448", test_wc_ed448_sign_msg), \
TEST_DECL_GROUP("ed448", test_wc_ed448_sign_msg_pubonly_fails), \
TEST_DECL_GROUP("ed448", test_wc_ed448_import_public), \
TEST_DECL_GROUP("ed448", test_wc_ed448_import_private_key), \
TEST_DECL_GROUP("ed448", test_wc_ed448_export), \
Expand Down
78 changes: 78 additions & 0 deletions tests/api/test_mldsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,84 @@ int test_wc_dilithium(void)
return EXPECT_RESULT();
}

/*
* Test that wc_dilithium_sign_msg() rejects a public-key-only key object.
* A key with prvKeySet=0 must not silently sign with zeroed key data.
*/
int test_wc_dilithium_sign_pubonly_fails(void)
{
EXPECT_DECLS;
#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)
#if defined(HAVE_DILITHIUM) && defined(WOLFSSL_WC_DILITHIUM) && \
!defined(WOLFSSL_DILITHIUM_NO_SIGN) && \
!defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) && \
!defined(WOLFSSL_DILITHIUM_NO_CTX)
dilithium_key* key;
dilithium_key* pubOnlyKey;
WC_RNG rng;
byte* pubBuf = NULL;
word32 pubLen = DILITHIUM_MAX_PUB_KEY_SIZE;
byte msg[] = "test message for pubonly check";
byte* sig = NULL;
word32 sigLen = DILITHIUM_MAX_SIG_SIZE;

key = (dilithium_key*)XMALLOC(sizeof(*key), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(key);
pubOnlyKey = (dilithium_key*)XMALLOC(sizeof(*pubOnlyKey), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(pubOnlyKey);
pubBuf = (byte*)XMALLOC(DILITHIUM_MAX_PUB_KEY_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(pubBuf);
sig = (byte*)XMALLOC(DILITHIUM_MAX_SIG_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(sig);

if (key != NULL)
XMEMSET(key, 0, sizeof(*key));
if (pubOnlyKey != NULL)
XMEMSET(pubOnlyKey, 0, sizeof(*pubOnlyKey));
XMEMSET(&rng, 0, sizeof(rng));

ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_dilithium_init(key), 0);
ExpectIntEQ(wc_dilithium_init(pubOnlyKey), 0);

#ifndef WOLFSSL_NO_ML_DSA_44
ExpectIntEQ(wc_dilithium_set_level(key, WC_ML_DSA_44), 0);
ExpectIntEQ(wc_dilithium_set_level(pubOnlyKey, WC_ML_DSA_44), 0);
#elif !defined(WOLFSSL_NO_ML_DSA_65)
ExpectIntEQ(wc_dilithium_set_level(key, WC_ML_DSA_65), 0);
ExpectIntEQ(wc_dilithium_set_level(pubOnlyKey, WC_ML_DSA_65), 0);
#else
ExpectIntEQ(wc_dilithium_set_level(key, WC_ML_DSA_87), 0);
ExpectIntEQ(wc_dilithium_set_level(pubOnlyKey, WC_ML_DSA_87), 0);
#endif

/* Generate a real key pair and export its public key. */
ExpectIntEQ(wc_dilithium_make_key(key, &rng), 0);
ExpectIntEQ(wc_dilithium_export_public(key, pubBuf, &pubLen), 0);

/* Import only the public key into a fresh key object. */
ExpectIntEQ(wc_dilithium_import_public(pubBuf, pubLen, pubOnlyKey), 0);

/* Signing with a public-key-only object must fail. */
ExpectIntEQ(wc_dilithium_sign_ctx_msg(NULL, 0, msg, sizeof(msg), sig,
&sigLen, pubOnlyKey, &rng), WC_NO_ERR_TRACE(BAD_FUNC_ARG));

DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_dilithium_free(pubOnlyKey);
wc_dilithium_free(key);
XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(pubBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(pubOnlyKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#endif
return EXPECT_RESULT();
} /* END test_wc_dilithium_sign_pubonly_fails */

int test_wc_dilithium_make_key(void)
{
EXPECT_DECLS;
Expand Down
2 changes: 2 additions & 0 deletions tests/api/test_mldsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <tests/api/api_decl.h>

int test_wc_dilithium(void);
int test_wc_dilithium_sign_pubonly_fails(void);
int test_wc_dilithium_make_key(void);
int test_wc_dilithium_sign(void);
int test_wc_dilithium_verify(void);
Expand All @@ -42,6 +43,7 @@ int test_mldsa_pkcs12(void);

#define TEST_MLDSA_DECLS \
TEST_DECL_GROUP("mldsa", test_wc_dilithium), \
TEST_DECL_GROUP("mldsa", test_wc_dilithium_sign_pubonly_fails), \
TEST_DECL_GROUP("mldsa", test_wc_dilithium_make_key), \
TEST_DECL_GROUP("mldsa", test_wc_dilithium_sign), \
TEST_DECL_GROUP("mldsa", test_wc_dilithium_verify), \
Expand Down
78 changes: 78 additions & 0 deletions tests/api/test_mlkem.c
Original file line number Diff line number Diff line change
Expand Up @@ -3872,3 +3872,81 @@ int test_wc_mlkem_decapsulate_kats(void)
return EXPECT_RESULT();
}

/*
* Test that wc_MlKemKey_Decapsulate() rejects a public-key-only key object.
* A key with MLKEM_FLAG_PUB_SET but not MLKEM_FLAG_PRIV_SET must not
* silently decapsulate with zeroed private key data.
*/
int test_wc_mlkem_decapsulate_pubonly_fails(void)
{
EXPECT_DECLS;
#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)
#if defined(WOLFSSL_HAVE_MLKEM) && defined(WOLFSSL_WC_MLKEM) && \
!defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_MLKEM_NO_DECAPSULATE) && \
!defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) && \
!defined(WOLFSSL_MLKEM_NO_MAKE_KEY)
MlKemKey* fullKey;
MlKemKey* pubOnlyKey;
WC_RNG rng;
byte ct[WC_ML_KEM_MAX_CIPHER_TEXT_SIZE];
byte ss[WC_ML_KEM_SS_SZ];
byte ssDec[WC_ML_KEM_SS_SZ];
byte pubBuf[WC_ML_KEM_MAX_PUBLIC_KEY_SIZE];
word32 pubLen = 0;
word32 ctLen = 0;

fullKey = (MlKemKey*)XMALLOC(sizeof(*fullKey), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(fullKey);
pubOnlyKey = (MlKemKey*)XMALLOC(sizeof(*pubOnlyKey), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(pubOnlyKey);

XMEMSET(&rng, 0, sizeof(rng));
ExpectIntEQ(wc_InitRng(&rng), 0);

#ifndef WOLFSSL_NO_ML_KEM_768
ExpectIntEQ(wc_MlKemKey_Init(fullKey, WC_ML_KEM_768, NULL,
INVALID_DEVID), 0);
ExpectIntEQ(wc_MlKemKey_Init(pubOnlyKey, WC_ML_KEM_768, NULL,
INVALID_DEVID), 0);
#elif !defined(WOLFSSL_NO_ML_KEM_512)
ExpectIntEQ(wc_MlKemKey_Init(fullKey, WC_ML_KEM_512, NULL,
INVALID_DEVID), 0);
ExpectIntEQ(wc_MlKemKey_Init(pubOnlyKey, WC_ML_KEM_512, NULL,
INVALID_DEVID), 0);
#else
ExpectIntEQ(wc_MlKemKey_Init(fullKey, WC_ML_KEM_1024, NULL,
INVALID_DEVID), 0);
ExpectIntEQ(wc_MlKemKey_Init(pubOnlyKey, WC_ML_KEM_1024, NULL,
INVALID_DEVID), 0);
#endif

/* Get correct sizes for this key type. */
ExpectIntEQ(wc_MlKemKey_PublicKeySize(fullKey, &pubLen), 0);
ExpectIntEQ(wc_MlKemKey_CipherTextSize(fullKey, &ctLen), 0);

/* Generate a real key pair. */
ExpectIntEQ(wc_MlKemKey_MakeKey(fullKey, &rng), 0);

/* Encapsulate with the full key to get a valid ciphertext. */
ExpectIntEQ(wc_MlKemKey_Encapsulate(fullKey, ct, ss, &rng), 0);

/* Export and import only the public key. */
ExpectIntEQ(wc_MlKemKey_EncodePublicKey(fullKey, pubBuf, pubLen), 0);
ExpectIntEQ(wc_MlKemKey_DecodePublicKey(pubOnlyKey, pubBuf, pubLen), 0);

/* Decapsulating with a public-key-only object must fail. */
ExpectIntEQ(wc_MlKemKey_Decapsulate(pubOnlyKey, ssDec, ct, ctLen),
WC_NO_ERR_TRACE(BAD_STATE_E));

DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_MlKemKey_Free(pubOnlyKey);
wc_MlKemKey_Free(fullKey);
XFREE(pubOnlyKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(fullKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#endif
return EXPECT_RESULT();
} /* END test_wc_mlkem_decapsulate_pubonly_fails */

4 changes: 3 additions & 1 deletion tests/api/test_mlkem.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@
int test_wc_mlkem_make_key_kats(void);
int test_wc_mlkem_encapsulate_kats(void);
int test_wc_mlkem_decapsulate_kats(void);
int test_wc_mlkem_decapsulate_pubonly_fails(void);

#define TEST_MLKEM_DECLS \
TEST_DECL_GROUP("mlkem", test_wc_mlkem_make_key_kats), \
TEST_DECL_GROUP("mlkem", test_wc_mlkem_encapsulate_kats), \
TEST_DECL_GROUP("mlkem", test_wc_mlkem_decapsulate_kats)
TEST_DECL_GROUP("mlkem", test_wc_mlkem_decapsulate_kats), \
TEST_DECL_GROUP("mlkem", test_wc_mlkem_decapsulate_pubonly_fails)

#endif /* WOLFCRYPT_TEST_MLKEM_H */
3 changes: 3 additions & 0 deletions wolfcrypt/src/dilithium.c
Original file line number Diff line number Diff line change
Expand Up @@ -10192,6 +10192,9 @@ int wc_dilithium_sign_ctx_msg(const byte* ctx, byte ctxLen, const byte* msg,
if ((ret == 0) && (ctx == NULL) && (ctxLen > 0)) {
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && (!key->prvKeySet)) {
ret = BAD_FUNC_ARG;
}

#ifdef WOLF_CRYPTO_CB
if (ret == 0) {
Expand Down
2 changes: 2 additions & 0 deletions wolfcrypt/src/ed25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,8 @@ int wc_ed25519_sign_msg_ex(const byte* in, word32 inLen, byte* out,

if (!key->pubKeySet)
return BAD_FUNC_ARG;
if (!key->privKeySet)
return BAD_FUNC_ARG;

/* check and set up out length */
if (*outLen < ED25519_SIG_SIZE) {
Expand Down
3 changes: 3 additions & 0 deletions wolfcrypt/src/ed448.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,9 @@ int wc_ed448_sign_msg_ex(const byte* in, word32 inLen, byte* out,
if ((ret == 0) && (!key->pubKeySet)) {
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && (!key->privKeySet)) {
ret = BAD_FUNC_ARG;
}

/* check and set up out length */
if ((ret == 0) && (*outLen < ED448_SIG_SIZE)) {
Expand Down
3 changes: 3 additions & 0 deletions wolfcrypt/src/wc_mlkem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1481,6 +1481,9 @@ int wc_MlKemKey_Decapsulate(MlKemKey* key, unsigned char* ss,
if ((key == NULL) || (ss == NULL) || (ct == NULL)) {
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && ((key->flags & MLKEM_FLAG_PRIV_SET) == 0)) {
ret = BAD_STATE_E;
}

if (ret == 0) {
/* Establish cipher text size based on key type. */
Expand Down
Loading