Skip to content

Commit c24261b

Browse files
author
Emma Stensland
committed
tests: cover the derived ML-DSA public key
1 parent 9510f3a commit c24261b

2 files changed

Lines changed: 549 additions & 18 deletions

File tree

‎tests/auth.c‎

Lines changed: 165 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1423,23 +1423,13 @@ static void test_pubkey_auth_wrong_key(void)
14231423
#if !defined(WOLFSSH_NO_MLDSA) && !defined(WOLFSSH_NO_MLDSA44) && \
14241424
defined(WOLFSSL_MLDSA_PRIVATE_KEY) && !defined(WOLFSSL_MLDSA_NO_ASN1) && \
14251425
!defined(WOLFSSL_MLDSA_NO_MAKE_KEY)
1426-
/* Covers the private-only ML-DSA host key through the real load path
1427-
* (wolfSSH_CTX_UsePrivateKey_buffer), not just IdentifyAsn1Key called
1428-
* directly as in the unit test. */
1429-
static void test_pubkey_load_mldsa_privonly_hostkey(void)
1426+
/* Generate a private-only ML-DSA-44 host key in PKCS#8 DER. Caller frees. */
1427+
static byte* mldsa_privonly_hostkey_der(int* derSz)
14301428
{
1431-
WOLFSSH_CTX* ctx;
14321429
MlDsaKey mlKey;
14331430
WC_RNG mlRng;
14341431
byte* mlDer;
14351432
int mlDerSz;
1436-
#ifdef WOLFSSH_HAVE_MLDSA_DERIVE_PUB
1437-
const int expect = WS_SUCCESS;
1438-
#else
1439-
const int expect = WS_CRYPTO_FAILED;
1440-
#endif
1441-
1442-
printf("Testing ML-DSA private-only host key load\n");
14431433

14441434
WMEMSET(&mlKey, 0, sizeof(mlKey));
14451435
AssertIntEQ(wc_MlDsaKey_Init(&mlKey, NULL, INVALID_DEVID), 0);
@@ -1455,16 +1445,167 @@ static void test_pubkey_load_mldsa_privonly_hostkey(void)
14551445
wc_MlDsaKey_Free(&mlKey);
14561446
AssertIntGT(mlDerSz, 0);
14571447

1448+
*derSz = mlDerSz;
1449+
return mlDer;
1450+
}
1451+
1452+
/* Covers the private-only ML-DSA host key through the real load path
1453+
* (wolfSSH_CTX_UsePrivateKey_buffer), not just IdentifyAsn1Key called
1454+
* directly as in the unit test. */
1455+
static void test_pubkey_load_mldsa_privonly_hostkey(void)
1456+
{
1457+
WOLFSSH_CTX* ctx;
1458+
byte* mlDer;
1459+
int mlDerSz;
1460+
#ifdef WOLFSSH_HAVE_MLDSA_DERIVE_PUB
1461+
const int expect = WS_SUCCESS;
1462+
#else
1463+
const int expect = WS_CRYPTO_FAILED;
1464+
#endif
1465+
1466+
printf("Testing ML-DSA private-only host key load\n");
1467+
1468+
mlDer = mldsa_privonly_hostkey_der(&mlDerSz);
1469+
14581470
ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL);
14591471
AssertNotNull(ctx);
14601472
AssertIntEQ(wolfSSH_CTX_UsePrivateKey_buffer(ctx, mlDer, (word32)mlDerSz,
14611473
WOLFSSH_FORMAT_ASN1), expect);
14621474
wolfSSH_CTX_free(ctx);
14631475

1476+
WMEMSET(mlDer, 0, mlDerSz);
14641477
WFREE(mlDer, NULL, 0);
14651478
}
1466-
#endif /* !WOLFSSH_NO_MLDSA && !WOLFSSH_NO_MLDSA44 && WOLFSSL_MLDSA_PRIVATE_KEY
1467-
* && !WOLFSSL_MLDSA_NO_ASN1 && !WOLFSSL_MLDSA_NO_MAKE_KEY */
1479+
1480+
#if defined(WOLFSSH_HAVE_MLDSA_DERIVE_PUB) && !defined(WOLFSSH_NO_ECDSA)
1481+
/* ML-DSA counterpart to test_pubkey_auth_ed25519_privonly_hostkey: a real
1482+
* handshake with a private-only host key, exercising the derived public
1483+
* key all the way through SendKexGetSigningKey. */
1484+
static void test_pubkey_auth_mldsa_privonly_hostkey(void)
1485+
{
1486+
PubkeyServerCtx sCtx = {0};
1487+
PubkeyClientCtx cCtx;
1488+
byte pubKeyBuf[512];
1489+
byte* p = pubKeyBuf;
1490+
word32 pubKeySz = sizeof(pubKeyBuf);
1491+
const byte* pubKeyType = NULL;
1492+
word32 pubKeyTypeSz = 0;
1493+
byte privKeyBuf[1300];
1494+
byte* privKeyPtr = privKeyBuf;
1495+
word32 privKeySz = sizeof(privKeyBuf);
1496+
const byte* privKeyType = NULL;
1497+
word32 privKeyTypeSz = 0;
1498+
byte* hostKeyDer;
1499+
int hostKeyDerSz;
1500+
1501+
printf("Testing ML-DSA private-only host key at KEX (derived pubkey)\n");
1502+
1503+
hostKeyDer = mldsa_privonly_hostkey_der(&hostKeyDerSz);
1504+
1505+
AssertIntEQ(wolfSSH_ReadKey_buffer((const byte*)hanselPublicEcc,
1506+
(word32)WSTRLEN(hanselPublicEcc), WOLFSSH_FORMAT_SSH,
1507+
&p, &pubKeySz, &pubKeyType, &pubKeyTypeSz, NULL), WS_SUCCESS);
1508+
1509+
AssertIntEQ(wc_Sha256Hash(pubKeyBuf, pubKeySz, sCtx.hash), 0);
1510+
1511+
AssertIntEQ(wolfSSH_ReadKey_buffer(hanselPrivateEcc, hanselPrivateEccSz,
1512+
WOLFSSH_FORMAT_ASN1,
1513+
&privKeyPtr, &privKeySz, &privKeyType, &privKeyTypeSz, NULL),
1514+
WS_SUCCESS);
1515+
1516+
cCtx.publicKeyType = pubKeyType;
1517+
cCtx.publicKeyTypeSz = pubKeyTypeSz;
1518+
cCtx.publicKey = pubKeyBuf;
1519+
cCtx.publicKeySz = pubKeySz;
1520+
cCtx.privateKey = privKeyBuf;
1521+
cCtx.privateKeySz = privKeySz;
1522+
1523+
run_pubkey_test_ex(&sCtx, &cCtx, WS_SUCCESS, hostKeyDer,
1524+
(word32)hostKeyDerSz);
1525+
1526+
WMEMSET(privKeyBuf, 0, sizeof(privKeyBuf));
1527+
WMEMSET(hostKeyDer, 0, hostKeyDerSz);
1528+
WFREE(hostKeyDer, NULL, 0);
1529+
}
1530+
#endif /* WOLFSSH_HAVE_MLDSA_DERIVE_PUB && !WOLFSSH_NO_ECDSA */
1531+
1532+
#if defined(WOLFSSH_HAVE_MLDSA_DERIVE_PUB) && \
1533+
defined(WOLFSSL_MLDSA_PUBLIC_KEY) && \
1534+
(!defined(WOLFSSH_NO_ECDSA) || !defined(WOLFSSH_NO_RSA))
1535+
/* User auth with a private-only ML-DSA-44 client key, read the way an
1536+
* application would, through wolfSSH_ReadKey_buffer(). */
1537+
static void test_pubkey_auth_mldsa_privonly_userkey(void)
1538+
{
1539+
PubkeyServerCtx sCtx = {0};
1540+
PubkeyClientCtx cCtx;
1541+
MlDsaKey mlKey;
1542+
WC_RNG rng;
1543+
byte* pubDer;
1544+
int pubDerSz;
1545+
byte* privDer;
1546+
int privDerSz;
1547+
byte* pubBlob = NULL;
1548+
word32 pubBlobSz = 0;
1549+
const byte* pubType = NULL;
1550+
word32 pubTypeSz = 0;
1551+
byte* privKey = NULL;
1552+
word32 privKeySz = 0;
1553+
const byte* privType = NULL;
1554+
word32 privTypeSz = 0;
1555+
1556+
printf("Testing ML-DSA private-only client key for user auth\n");
1557+
1558+
WMEMSET(&mlKey, 0, sizeof(mlKey));
1559+
AssertIntEQ(wc_MlDsaKey_Init(&mlKey, NULL, INVALID_DEVID), 0);
1560+
AssertIntEQ(wc_MlDsaKey_SetParams(&mlKey, WC_ML_DSA_44), 0);
1561+
AssertIntEQ(wc_InitRng(&rng), 0);
1562+
AssertIntEQ(wc_MlDsaKey_MakeKey(&mlKey, &rng), 0);
1563+
wc_FreeRng(&rng);
1564+
1565+
pubDer = (byte*)WMALLOC(WC_MLDSA_44_PUB_KEY_DER_SIZE, NULL, 0);
1566+
AssertNotNull(pubDer);
1567+
pubDerSz = wc_MlDsaKey_PublicKeyToDer(&mlKey, pubDer,
1568+
WC_MLDSA_44_PUB_KEY_DER_SIZE, 1);
1569+
AssertIntGT(pubDerSz, 0);
1570+
privDer = (byte*)WMALLOC(WC_MLDSA_44_PRV_KEY_DER_SIZE, NULL, 0);
1571+
AssertNotNull(privDer);
1572+
privDerSz = wc_MlDsaKey_PrivateKeyToDer(&mlKey, privDer,
1573+
WC_MLDSA_44_PRV_KEY_DER_SIZE);
1574+
wc_MlDsaKey_Free(&mlKey);
1575+
AssertIntGT(privDerSz, 0);
1576+
1577+
AssertIntEQ(wolfSSH_ReadKey_buffer_ex(pubDer, (word32)pubDerSz,
1578+
WOLFSSH_FORMAT_ASN1, &pubBlob, &pubBlobSz, &pubType, &pubTypeSz,
1579+
0, NULL), WS_SUCCESS);
1580+
AssertIntEQ(wolfSSH_ReadKey_buffer(privDer, (word32)privDerSz,
1581+
WOLFSSH_FORMAT_ASN1, &privKey, &privKeySz, &privType,
1582+
&privTypeSz, NULL), WS_SUCCESS);
1583+
AssertIntEQ(privTypeSz, pubTypeSz);
1584+
AssertIntEQ(WMEMCMP(privType, pubType, pubTypeSz), 0);
1585+
1586+
AssertIntEQ(wc_Sha256Hash(pubBlob, pubBlobSz, sCtx.hash), 0);
1587+
1588+
cCtx.publicKeyType = pubType;
1589+
cCtx.publicKeyTypeSz = pubTypeSz;
1590+
cCtx.publicKey = pubBlob;
1591+
cCtx.publicKeySz = pubBlobSz;
1592+
cCtx.privateKey = privKey;
1593+
cCtx.privateKeySz = privKeySz;
1594+
1595+
run_pubkey_test_ex(&sCtx, &cCtx, WS_SUCCESS, NULL, 0);
1596+
1597+
WMEMSET(privKey, 0, privKeySz);
1598+
WFREE(privKey, NULL, DYNTYPE_PRIVKEY);
1599+
WFREE(pubBlob, NULL, DYNTYPE_PRIVKEY);
1600+
WMEMSET(privDer, 0, privDerSz);
1601+
WFREE(privDer, NULL, 0);
1602+
WFREE(pubDer, NULL, 0);
1603+
}
1604+
#endif /* WOLFSSH_HAVE_MLDSA_DERIVE_PUB && WOLFSSL_MLDSA_PUBLIC_KEY &&
1605+
* (!WOLFSSH_NO_ECDSA || !WOLFSSH_NO_RSA) */
1606+
#endif /* !WOLFSSH_NO_MLDSA && !WOLFSSH_NO_MLDSA44
1607+
* && WOLFSSL_MLDSA_PRIVATE_KEY && !WOLFSSL_MLDSA_NO_ASN1
1608+
* && !WOLFSSL_MLDSA_NO_MAKE_KEY */
14681609

14691610
#if !defined(WOLFSSH_NO_ED25519) && defined(HAVE_ED25519) && \
14701611
defined(HAVE_ED25519_MAKE_KEY) && defined(HAVE_ED25519_KEY_EXPORT)
@@ -1599,6 +1740,8 @@ static void test_pubkey_auth_ecdsa_privonly_hostkey(void)
15991740
run_pubkey_test_ex(&sCtx, &cCtx, WS_SUCCESS, hostKeyDer,
16001741
(word32)hostKeyDerSz);
16011742

1743+
WMEMSET(privKeyBuf, 0, sizeof(privKeyBuf));
1744+
WMEMSET(hostKeyDer, 0, hostKeyDerSz);
16021745
WFREE(hostKeyDer, NULL, 0);
16031746
}
16041747
#endif /* !WOLFSSH_NO_ECDSA && !WOLFSSH_NO_RSA */
@@ -2514,6 +2657,14 @@ int wolfSSH_AuthTest(int argc, char** argv)
25142657
defined(WOLFSSL_MLDSA_PRIVATE_KEY) && !defined(WOLFSSL_MLDSA_NO_ASN1) && \
25152658
!defined(WOLFSSL_MLDSA_NO_MAKE_KEY)
25162659
test_pubkey_load_mldsa_privonly_hostkey();
2660+
#if defined(WOLFSSH_HAVE_MLDSA_DERIVE_PUB) && !defined(WOLFSSH_NO_ECDSA)
2661+
test_pubkey_auth_mldsa_privonly_hostkey();
2662+
#endif
2663+
#if defined(WOLFSSH_HAVE_MLDSA_DERIVE_PUB) && \
2664+
defined(WOLFSSL_MLDSA_PUBLIC_KEY) && \
2665+
(!defined(WOLFSSH_NO_ECDSA) || !defined(WOLFSSH_NO_RSA))
2666+
test_pubkey_auth_mldsa_privonly_userkey();
2667+
#endif
25172668
#endif
25182669
#endif /* !NO_SHA256 */
25192670

0 commit comments

Comments
 (0)