Skip to content

Commit fca19a4

Browse files
author
Emma Stensland
committed
Test ML-DSA export contract for a private-only key
1 parent 3180568 commit fca19a4

4 files changed

Lines changed: 210 additions & 9 deletions

File tree

‎doc/dox_comments/header_files/wc_mldsa.h‎

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -843,14 +843,16 @@ int wc_MlDsaKey_ImportKey(wc_MlDsaKey* key, const byte* priv, word32 privSz,
843843
size of out; on success it is updated to the bytes written.
844844
845845
\return 0 on success.
846-
\return BAD_FUNC_ARG if any required pointer is NULL.
846+
\return BAD_FUNC_ARG if any required pointer is NULL, or the public
847+
key is not set.
847848
\return BUFFER_E if *outLen is smaller than the public key size.
848849
849850
\param [in] key Pointer to a wc_MlDsaKey with a public key.
850851
\param [out] out Buffer that receives the public key.
851852
\param [in,out] outLen In: size of out. Out: bytes written.
852853
853854
\sa wc_MlDsaKey_ImportPubRaw
855+
\sa wc_MlDsaKey_MakePublicKey
854856
*/
855857
int wc_MlDsaKey_ExportPubRaw(wc_MlDsaKey* key, byte* out, word32* outLen);
856858

@@ -904,6 +906,9 @@ int wc_MlDsaKey_ExportKey(wc_MlDsaKey* key, byte* priv, word32 *privSz,
904906
905907
Only available when WOLFSSL_MLDSA_NO_ASN1 is not defined.
906908
909+
A private-only encoding leaves the public key unset; derive it with
910+
wc_MlDsaKey_MakePublicKey() before exporting.
911+
907912
\return 0 on success.
908913
\return BAD_FUNC_ARG if any required pointer is NULL.
909914
\return ASN_PARSE_E on malformed encoding.
@@ -916,6 +921,7 @@ int wc_MlDsaKey_ExportKey(wc_MlDsaKey* key, byte* priv, word32 *privSz,
916921
917922
\sa wc_MlDsaKey_PrivateKeyToDer
918923
\sa wc_MlDsaKey_PublicKeyDecode
924+
\sa wc_MlDsaKey_MakePublicKey
919925
*/
920926
int wc_MlDsaKey_PrivateKeyDecode(wc_MlDsaKey* key, const byte* input,
921927
word32 inSz, word32* inOutIdx);
@@ -954,8 +960,8 @@ int wc_MlDsaKey_PublicKeyDecode(wc_MlDsaKey* key, const byte* input,
954960
Pass NULL as output to query the required buffer size.
955961
956962
\return Size of the encoded DER in bytes on success.
957-
\return BAD_FUNC_ARG if key is NULL or no parameter set is
958-
selected.
963+
\return BAD_FUNC_ARG if key is NULL, no parameter set is selected,
964+
or the public key is not set.
959965
\return BUFFER_E if output is non-NULL and inLen is smaller than
960966
the required size.
961967
@@ -968,6 +974,7 @@ int wc_MlDsaKey_PublicKeyDecode(wc_MlDsaKey* key, const byte* input,
968974
969975
\sa wc_MlDsaKey_PublicKeyDecode
970976
\sa wc_MlDsaKey_KeyToDer
977+
\sa wc_MlDsaKey_MakePublicKey
971978
*/
972979
int wc_MlDsaKey_PublicKeyToDer(wc_MlDsaKey* key, byte* output,
973980
word32 inLen, int withAlg);
@@ -980,9 +987,8 @@ int wc_MlDsaKey_PublicKeyToDer(wc_MlDsaKey* key, byte* output,
980987
the required buffer size.
981988
982989
\return Size of the encoded DER in bytes on success.
983-
\return BAD_FUNC_ARG if key is NULL or no parameter set is
984-
selected.
985-
\return MISSING_KEY if the private key has not been set.
990+
\return BAD_FUNC_ARG if key is NULL, no parameter set is selected,
991+
the private key has not been set, or the public key is not set.
986992
\return BUFFER_E if output is non-NULL and inLen is too small.
987993
988994
\param [in] key Pointer to a wc_MlDsaKey with the private key.
@@ -993,6 +999,7 @@ int wc_MlDsaKey_PublicKeyToDer(wc_MlDsaKey* key, byte* output,
993999
\sa wc_MlDsaKey_PrivateKeyDecode
9941000
\sa wc_MlDsaKey_PrivateKeyToDer
9951001
\sa wc_MlDsaKey_PublicKeyToDer
1002+
\sa wc_MlDsaKey_MakePublicKey
9961003
*/
9971004
int wc_MlDsaKey_KeyToDer(wc_MlDsaKey* key, byte* output, word32 inLen);
9981005

‎tests/api/test_mldsa.c‎

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7890,6 +7890,196 @@ int test_mldsa_make_public_key(void)
78907890
}
78917891

78927892

7893+
int test_mldsa_make_public_key_then_export(void)
7894+
{
7895+
EXPECT_DECLS;
7896+
/* Runs under WOLF_CRYPTO_CB_FIND too. */
7897+
#if defined(WOLFSSL_HAVE_MLDSA) && !defined(WOLFSSL_MLDSA_NO_ASN1) && \
7898+
!defined(WOLFSSL_MLDSA_ASSIGN_KEY) && \
7899+
!defined(WOLFSSL_MLDSA_NO_MAKE_KEY) && \
7900+
!defined(WOLFSSL_MLDSA_NO_SIGN) && !defined(WOLFSSL_MLDSA_NO_VERIFY) && \
7901+
defined(WOLFSSL_MLDSA_PUBLIC_KEY)
7902+
wc_MlDsaKey* privKey;
7903+
wc_MlDsaKey* pubKey;
7904+
word32 idx;
7905+
byte derivedPub[WC_MLDSA_87_PUB_KEY_SIZE];
7906+
word32 derivedPubSz;
7907+
7908+
privKey = (wc_MlDsaKey*)XMALLOC(sizeof(*privKey), NULL,
7909+
DYNAMIC_TYPE_TMP_BUFFER);
7910+
ExpectNotNull(privKey);
7911+
pubKey = (wc_MlDsaKey*)XMALLOC(sizeof(*pubKey), NULL,
7912+
DYNAMIC_TYPE_TMP_BUFFER);
7913+
ExpectNotNull(pubKey);
7914+
if (privKey != NULL) {
7915+
XMEMSET(privKey, 0, sizeof(*privKey));
7916+
}
7917+
if (pubKey != NULL) {
7918+
XMEMSET(pubKey, 0, sizeof(*pubKey));
7919+
}
7920+
7921+
#ifndef WOLFSSL_NO_ML_DSA_44
7922+
ExpectIntEQ(wc_MlDsaKey_Init(privKey, NULL, INVALID_DEVID), 0);
7923+
ExpectIntEQ(wc_MlDsaKey_SetParams(privKey, WC_ML_DSA_44), 0);
7924+
7925+
/* Private-only DER: Export/Der accessors fail until derived. */
7926+
idx = 0;
7927+
ExpectIntEQ(wc_MlDsaKey_PrivateKeyDecode(privKey, mldsa44_priv_only,
7928+
sizeof_mldsa44_priv_only, &idx), 0);
7929+
ExpectIntEQ(privKey->pubKeySet, 0);
7930+
derivedPubSz = sizeof(derivedPub);
7931+
ExpectIntEQ(wc_MlDsaKey_ExportPubRaw(privKey, derivedPub, &derivedPubSz),
7932+
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
7933+
ExpectIntEQ(privKey->pubKeySet, 0);
7934+
7935+
/* Explicit derive, then export succeeds. */
7936+
ExpectIntEQ(wc_MlDsaKey_MakePublicKey(privKey), 0);
7937+
ExpectIntEQ(privKey->pubKeySet, 1);
7938+
derivedPubSz = sizeof(derivedPub);
7939+
ExpectIntEQ(wc_MlDsaKey_ExportPubRaw(privKey, derivedPub, &derivedPubSz),
7940+
0);
7941+
7942+
/* Confirm derived public key matches known public key. */
7943+
ExpectIntEQ(wc_MlDsaKey_Init(pubKey, NULL, INVALID_DEVID), 0);
7944+
ExpectIntEQ(wc_MlDsaKey_SetParams(pubKey, WC_ML_DSA_44), 0);
7945+
idx = 0;
7946+
ExpectIntEQ(wc_MlDsaKey_PublicKeyDecode(pubKey, mldsa44_pub_spki,
7947+
sizeof_mldsa44_pub_spki, &idx), 0);
7948+
ExpectIntEQ(XMEMCMP(privKey->p, pubKey->p, WC_MLDSA_44_PUB_KEY_SIZE), 0);
7949+
7950+
/* KeyToDer: fails until derived, then matches known public key. */
7951+
{
7952+
wc_MlDsaKey* privKey2;
7953+
byte* der;
7954+
7955+
privKey2 = (wc_MlDsaKey*)XMALLOC(sizeof(*privKey2), NULL,
7956+
DYNAMIC_TYPE_TMP_BUFFER);
7957+
ExpectNotNull(privKey2);
7958+
der = (byte*)XMALLOC(MLDSA_MAX_DER_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
7959+
ExpectNotNull(der);
7960+
if (privKey2 != NULL) {
7961+
XMEMSET(privKey2, 0, sizeof(*privKey2));
7962+
}
7963+
7964+
ExpectIntEQ(wc_MlDsaKey_Init(privKey2, NULL, INVALID_DEVID), 0);
7965+
ExpectIntEQ(wc_MlDsaKey_SetParams(privKey2, WC_ML_DSA_44), 0);
7966+
idx = 0;
7967+
ExpectIntEQ(wc_MlDsaKey_PrivateKeyDecode(privKey2, mldsa44_priv_only,
7968+
sizeof_mldsa44_priv_only, &idx), 0);
7969+
ExpectIntEQ(privKey2->pubKeySet, 0);
7970+
7971+
ExpectIntEQ(wc_MlDsaKey_KeyToDer(privKey2, der, MLDSA_MAX_DER_SIZE),
7972+
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
7973+
ExpectIntEQ(privKey2->pubKeySet, 0);
7974+
7975+
ExpectIntEQ(wc_MlDsaKey_MakePublicKey(privKey2), 0);
7976+
ExpectIntGT(wc_MlDsaKey_KeyToDer(privKey2, der, MLDSA_MAX_DER_SIZE),
7977+
0);
7978+
ExpectIntEQ(privKey2->pubKeySet, 1);
7979+
ExpectIntEQ(XMEMCMP(privKey2->p, pubKey->p, WC_MLDSA_44_PUB_KEY_SIZE),
7980+
0);
7981+
7982+
wc_MlDsaKey_Free(privKey2);
7983+
XFREE(privKey2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
7984+
XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
7985+
}
7986+
7987+
/* PublicKeyToDer: fails until derived, then succeeds. */
7988+
{
7989+
wc_MlDsaKey* privKey3;
7990+
byte* der;
7991+
7992+
privKey3 = (wc_MlDsaKey*)XMALLOC(sizeof(*privKey3), NULL,
7993+
DYNAMIC_TYPE_TMP_BUFFER);
7994+
ExpectNotNull(privKey3);
7995+
der = (byte*)XMALLOC(MLDSA_MAX_DER_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
7996+
ExpectNotNull(der);
7997+
if (privKey3 != NULL) {
7998+
XMEMSET(privKey3, 0, sizeof(*privKey3));
7999+
}
8000+
8001+
ExpectIntEQ(wc_MlDsaKey_Init(privKey3, NULL, INVALID_DEVID), 0);
8002+
ExpectIntEQ(wc_MlDsaKey_SetParams(privKey3, WC_ML_DSA_44), 0);
8003+
idx = 0;
8004+
ExpectIntEQ(wc_MlDsaKey_PrivateKeyDecode(privKey3, mldsa44_priv_only,
8005+
sizeof_mldsa44_priv_only, &idx), 0);
8006+
ExpectIntEQ(privKey3->pubKeySet, 0);
8007+
8008+
ExpectIntEQ(wc_MlDsaKey_PublicKeyToDer(privKey3, der,
8009+
MLDSA_MAX_DER_SIZE, 1), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
8010+
ExpectIntEQ(privKey3->pubKeySet, 0);
8011+
8012+
ExpectIntEQ(wc_MlDsaKey_MakePublicKey(privKey3), 0);
8013+
ExpectIntGT(wc_MlDsaKey_PublicKeyToDer(privKey3, der,
8014+
MLDSA_MAX_DER_SIZE, 1), 0);
8015+
ExpectIntEQ(privKey3->pubKeySet, 1);
8016+
ExpectIntEQ(XMEMCMP(privKey3->p, pubKey->p, WC_MLDSA_44_PUB_KEY_SIZE),
8017+
0);
8018+
8019+
wc_MlDsaKey_Free(privKey3);
8020+
XFREE(privKey3, NULL, DYNAMIC_TYPE_TMP_BUFFER);
8021+
XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
8022+
}
8023+
8024+
wc_MlDsaKey_Free(privKey);
8025+
wc_MlDsaKey_Free(pubKey);
8026+
#endif /* !WOLFSSL_NO_ML_DSA_44 */
8027+
8028+
#ifndef WOLFSSL_NO_ML_DSA_65
8029+
ExpectIntEQ(wc_MlDsaKey_Init(privKey, NULL, INVALID_DEVID), 0);
8030+
ExpectIntEQ(wc_MlDsaKey_SetParams(privKey, WC_ML_DSA_65), 0);
8031+
8032+
idx = 0;
8033+
ExpectIntEQ(wc_MlDsaKey_PrivateKeyDecode(privKey, mldsa65_priv_only,
8034+
sizeof_mldsa65_priv_only, &idx), 0);
8035+
ExpectIntEQ(privKey->pubKeySet, 0);
8036+
ExpectIntEQ(wc_MlDsaKey_MakePublicKey(privKey), 0);
8037+
ExpectIntEQ(privKey->pubKeySet, 1);
8038+
derivedPubSz = sizeof(derivedPub);
8039+
ExpectIntEQ(wc_MlDsaKey_ExportPubRaw(privKey, derivedPub, &derivedPubSz),
8040+
0);
8041+
8042+
ExpectIntEQ(wc_MlDsaKey_Init(pubKey, NULL, INVALID_DEVID), 0);
8043+
ExpectIntEQ(wc_MlDsaKey_SetParams(pubKey, WC_ML_DSA_65), 0);
8044+
idx = 0;
8045+
ExpectIntEQ(wc_MlDsaKey_PublicKeyDecode(pubKey, mldsa65_pub_spki,
8046+
sizeof_mldsa65_pub_spki, &idx), 0);
8047+
ExpectIntEQ(XMEMCMP(privKey->p, pubKey->p, WC_MLDSA_65_PUB_KEY_SIZE), 0);
8048+
8049+
wc_MlDsaKey_Free(privKey);
8050+
wc_MlDsaKey_Free(pubKey);
8051+
#endif /* !WOLFSSL_NO_ML_DSA_65 */
8052+
8053+
#ifndef WOLFSSL_NO_ML_DSA_87
8054+
ExpectIntEQ(wc_MlDsaKey_Init(privKey, NULL, INVALID_DEVID), 0);
8055+
ExpectIntEQ(wc_MlDsaKey_SetParams(privKey, WC_ML_DSA_87), 0);
8056+
8057+
idx = 0;
8058+
ExpectIntEQ(wc_MlDsaKey_PrivateKeyDecode(privKey, mldsa87_priv_only,
8059+
sizeof_mldsa87_priv_only, &idx), 0);
8060+
ExpectIntEQ(privKey->pubKeySet, 0);
8061+
ExpectIntEQ(wc_MlDsaKey_MakePublicKey(privKey), 0);
8062+
ExpectIntEQ(privKey->pubKeySet, 1);
8063+
derivedPubSz = sizeof(derivedPub);
8064+
ExpectIntEQ(wc_MlDsaKey_ExportPubRaw(privKey, derivedPub, &derivedPubSz),
8065+
0);
8066+
8067+
ExpectIntEQ(wc_MlDsaKey_Init(pubKey, NULL, INVALID_DEVID), 0);
8068+
ExpectIntEQ(wc_MlDsaKey_SetParams(pubKey, WC_ML_DSA_87), 0);
8069+
idx = 0;
8070+
ExpectIntEQ(wc_MlDsaKey_PublicKeyDecode(pubKey, mldsa87_pub_spki,
8071+
sizeof_mldsa87_pub_spki, &idx), 0);
8072+
ExpectIntEQ(XMEMCMP(privKey->p, pubKey->p, WC_MLDSA_87_PUB_KEY_SIZE), 0);
8073+
8074+
wc_MlDsaKey_Free(privKey);
8075+
wc_MlDsaKey_Free(pubKey);
8076+
#endif /* !WOLFSSL_NO_ML_DSA_87 */
8077+
8078+
XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
8079+
XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
8080+
#endif
8081+
return EXPECT_RESULT();
8082+
}
78938083
int test_mldsa_verify_pubkeyset_guard(void)
78948084
{
78958085
EXPECT_DECLS;

‎tests/api/test_mldsa.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ int test_mldsa_der(void);
3939
int test_mldsa_oneasymkey_version(void);
4040
int test_mldsa_make_key_from_seed(void);
4141
int test_mldsa_make_public_key(void);
42+
int test_mldsa_make_public_key_then_export(void);
4243
int test_mldsa_verify_pubkeyset_guard(void);
4344
int test_mldsa_make_public_key_oom(void);
4445
int test_mldsa_make_public_key_cache_invalidation(void);
@@ -89,6 +90,7 @@ int test_wc_MlDsaKey_SetPrecompA(void);
8990
TEST_DECL_GROUP("mldsa", test_mldsa_oneasymkey_version), \
9091
TEST_DECL_GROUP("mldsa", test_mldsa_make_key_from_seed), \
9192
TEST_DECL_GROUP("mldsa", test_mldsa_make_public_key), \
93+
TEST_DECL_GROUP("mldsa", test_mldsa_make_public_key_then_export), \
9294
TEST_DECL_GROUP("mldsa", test_mldsa_verify_pubkeyset_guard), \
9395
TEST_DECL_GROUP("mldsa", test_mldsa_make_public_key_oom), \
9496
TEST_DECL_GROUP("mldsa", test_mldsa_make_public_key_cache_invalidation), \

‎wolfcrypt/src/wc_mldsa.c‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13375,7 +13375,8 @@ int wc_MlDsaKey_CheckKey(wc_MlDsaKey* key)
1337513375
* @param [in, out] outLen On in, the number of bytes in array.
1337613376
* On out, the number bytes put into array.
1337713377
* @return 0 on success.
13378-
* @return BAD_FUNC_ARG when a parameter is NULL.
13378+
* @return BAD_FUNC_ARG when a parameter is NULL, or when the public key is
13379+
* not set.
1337913380
* @return BUFFER_E when outLen is less than WC_MLDSA_44_PUB_KEY_SIZE.
1338013381
*/
1338113382
int wc_MlDsaKey_ExportPubRaw(wc_MlDsaKey* key, byte* out, word32* outLen)
@@ -14629,7 +14630,7 @@ int wc_MlDsaKey_PublicKeyDecode(wc_MlDsaKey* key, const byte* input,
1462914630
* @param [in] len Size of buffer in bytes.
1463014631
* @param [in] withAlg Whether to use SubjectPublicKeyInfo format.
1463114632
* @return Size of encoded data in bytes on success.
14632-
* @return BAD_FUNC_ARG when key is NULL.
14633+
* @return BAD_FUNC_ARG when key is NULL, or when the public key is not set.
1463314634
* @return MEMORY_E when dynamic memory allocation failed.
1463414635
*/
1463514636
int wc_MlDsaKey_PublicKeyToDer(wc_MlDsaKey* key, byte* output, word32 len,
@@ -14712,7 +14713,8 @@ int wc_MlDsaKey_PublicKeyToDer(wc_MlDsaKey* key, byte* output, word32 len,
1471214713
* @param [out] output Buffer to put encoded data in.
1471314714
* @param [in] len Size of buffer in bytes.
1471414715
* @return Size of encoded data in bytes on success.
14715-
* @return BAD_FUNC_ARG when key is NULL.
14716+
* @return BAD_FUNC_ARG when key is NULL, or when the public or private key
14717+
* is not set.
1471614718
* @return MEMORY_E when dynamic memory allocation failed.
1471714719
*/
1471814720
int wc_MlDsaKey_KeyToDer(wc_MlDsaKey* key, byte* output, word32 len)

0 commit comments

Comments
 (0)