mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 13:20:52 +02:00
Add privKeySet checks to Ed25519, Ed448, ML-DSA, and ML-KEM
This commit is contained in:
@@ -169,6 +169,50 @@ 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_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
|
||||
return EXPECT_RESULT();
|
||||
} /* END test_wc_ed25519_sign_msg_pubonly_fails */
|
||||
|
||||
/*
|
||||
* Testing wc_ed25519_import_public()
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
@@ -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), \
|
||||
|
||||
@@ -162,6 +162,50 @@ 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_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
|
||||
return EXPECT_RESULT();
|
||||
} /* END test_wc_ed448_sign_msg_pubonly_fails */
|
||||
|
||||
/*
|
||||
* Testing wc_ed448_import_public()
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
@@ -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), \
|
||||
|
||||
@@ -685,6 +685,82 @@ 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_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
|
||||
return EXPECT_RESULT();
|
||||
} /* END test_wc_dilithium_sign_pubonly_fails */
|
||||
|
||||
int test_wc_dilithium_make_key(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
|
||||
@@ -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);
|
||||
@@ -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), \
|
||||
|
||||
@@ -3872,3 +3872,79 @@ 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(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
|
||||
return EXPECT_RESULT();
|
||||
} /* END test_wc_mlkem_decapsulate_pubonly_fails */
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user