Skip to content

Commit 7d4fa32

Browse files
yosuke-wolfsslejohnstown
authored andcommitted
Fix minor issues and add unit test for IdentifyAsn1Key
1 parent bd75cb4 commit 7d4fa32

3 files changed

Lines changed: 227 additions & 7 deletions

File tree

src/internal.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,6 +1501,8 @@ int IdentifyAsn1Key(const byte* in, word32 inSz, int isPrivate, void* heap,
15011501
/* If decode was successful, this is an RSA key. */
15021502
if (ret == 0) {
15031503
key->keyId = ID_SSH_RSA;
1504+
} else {
1505+
wc_FreeRsaKey(&key->ks.rsa.key);
15041506
}
15051507
}
15061508
}
@@ -1533,7 +1535,12 @@ int IdentifyAsn1Key(const byte* in, word32 inSz, int isPrivate, void* heap,
15331535
case ECC_SECP521R1:
15341536
key->keyId = ID_ECDSA_SHA2_NISTP521;
15351537
break;
1538+
default:
1539+
/* Not a supported curve, so free the key */
1540+
wc_ecc_free(&key->ks.ecc.key);
15361541
}
1542+
} else {
1543+
wc_ecc_free(&key->ks.ecc.key);
15371544
}
15381545
}
15391546
}
@@ -1552,11 +1559,14 @@ int IdentifyAsn1Key(const byte* in, word32 inSz, int isPrivate, void* heap,
15521559
ret = wc_Ed25519PublicKeyDecode(in, &idx,
15531560
&key->ks.ed25519.key, inSz);
15541561
}
1555-
}
15561562

1557-
/* If decode was successful, this is a Ed25519 key. */
1558-
if (ret == 0)
1559-
key->keyId = ID_ED25519;
1563+
/* If decode was successful, this is a Ed25519 key. */
1564+
if (ret == 0) {
1565+
key->keyId = ID_ED25519;
1566+
} else {
1567+
wc_ed25519_free(&key->ks.ed25519.key);
1568+
}
1569+
}
15601570
}
15611571
#endif /* WOLFSSH_NO_ED25519 */
15621572

@@ -13052,7 +13062,7 @@ int SendKexDhReply(WOLFSSH* ssh)
1305213062
else if (useEcc) {
1305313063
ret = KeyAgreeEcdh_server(ssh, hashId, f_ptr, &fSz);
1305413064
}
13055-
if (useCurve25519) {
13065+
else if (useCurve25519) {
1305613066
ret = KeyAgreeCurve25519_server(ssh, hashId, f_ptr, &fSz);
1305713067
}
1305813068
else if (useEccMlKem) {

src/wolfsftp.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2775,7 +2775,6 @@ static int SFTP_CreateLongName(WS_SFTPNAME* name)
27752775

27762776
name->lName = (char*)WMALLOC(totalSz + 1, name->heap, DYNTYPE_SFTP);
27772777
if (name->lName == NULL) {
2778-
WFREE(name->lName, name->heap, DYNTYPE_SFTP);
27792778
return WS_MEMORY_E;
27802779
}
27812780
name->lSz = totalSz;
@@ -3987,6 +3986,7 @@ int wolfSSH_SFTP_RecvRead(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
39873986
if (res != NULL) {
39883987
if (wolfSSH_SFTP_CreateStatus(ssh, type, reqId, res, "English", NULL,
39893988
&outSz) != WS_SIZE_ONLY) {
3989+
WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER);
39903990
return WS_FATAL_ERROR;
39913991
}
39923992
if (outSz > strSz) {
@@ -5282,6 +5282,7 @@ int wolfSSH_SFTP_RecvFSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
52825282
if (ret == WS_SUCCESS) {
52835283
if (SFTP_SetHeader(ssh, reqId, WOLFSSH_FTP_ATTRS, sz, out)
52845284
!= WS_SUCCESS) {
5285+
WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER);
52855286
return WS_FATAL_ERROR;
52865287
}
52875288
SFTP_SetAttributes(ssh, out + WOLFSSH_SFTP_HEADER, sz, &atr);

tests/unit.c

Lines changed: 210 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1485,7 +1485,7 @@ static int CaptureIoSendAuthSvc(WOLFSSH* ssh, void* buf, word32 sz, void* ctx)
14851485
*
14861486
* For invalid-service cases the auth-method field is intentionally omitted
14871487
* from the payload. DoUserAuthRequest must short-circuit at the service-name
1488-
* check and still satisfy all three assertions proving it never tries to
1488+
* check and still satisfy all three assertions - proving it never tries to
14891489
* parse the missing auth-method field. If the short-circuit were absent,
14901490
* GetSize() for authNameSz would hit end-of-buffer and return WS_BUFFER_E,
14911491
* failing assertion 1.
@@ -1750,7 +1750,120 @@ static const byte unitTestRsaPrivKey[] = {
17501750
};
17511751
static const word32 unitTestRsaPrivKeySz =
17521752
(word32)sizeof(unitTestRsaPrivKey);
1753+
#endif /* WOLFSSH_NO_RSA */
1754+
1755+
/* Keys for test_IdentifyAsn1Key: inline DER so the test is self-contained
1756+
* in both filesystem and NO_FILESYSTEM builds. Each array matches the
1757+
* corresponding file under keys/. */
1758+
#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256
1759+
/* keys/server-key-ecc.der - P-256 RFC-5915 ECPrivateKey */
1760+
static const byte unitTestEcc256PrivKey[] = {
1761+
0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x61, 0x09, 0x99,
1762+
0x0B, 0x79, 0xD2, 0x5F, 0x28, 0x5A, 0x0F, 0x5D, 0x15, 0xCC,
1763+
0xA1, 0x56, 0x54, 0xF9, 0x2B, 0x39, 0x87, 0x21, 0x2D, 0xA7,
1764+
0x7D, 0x85, 0x7B, 0xB8, 0x7F, 0x38, 0xC6, 0x6D, 0xD5, 0xA0,
1765+
0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01,
1766+
0x07, 0xA1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x81, 0x13, 0xFF,
1767+
0xA4, 0x2B, 0xB7, 0x9C, 0x45, 0x74, 0x7A, 0x83, 0x4C, 0x61,
1768+
0xF3, 0x3F, 0xAD, 0x26, 0xCF, 0x22, 0xCD, 0xA9, 0xA3, 0xBC,
1769+
0xA5, 0x61, 0xB4, 0x7C, 0xE6, 0x62, 0xD4, 0xC2, 0xF7, 0x55,
1770+
0x43, 0x9A, 0x31, 0xFB, 0x80, 0x11, 0x20, 0xB5, 0x12, 0x4B,
1771+
0x24, 0xF5, 0x78, 0xD7, 0xFD, 0x22, 0xEF, 0x46, 0x35, 0xF0,
1772+
0x05, 0x58, 0x6B, 0x5F, 0x63, 0xC8, 0xDA, 0x1B, 0xC4, 0xF5,
1773+
0x69
1774+
};
1775+
#endif /* WOLFSSH_NO_ECDSA_SHA2_NISTP256 */
1776+
1777+
#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP384
1778+
/* keys/server-key-ecc-384.der - P-384 RFC-5915 ECPrivateKey */
1779+
static const byte unitTestEcc384PrivKey[] = {
1780+
0x30, 0x81, 0xA4, 0x02, 0x01, 0x01, 0x04, 0x30, 0x3E, 0xAD,
1781+
0xD2, 0xBB, 0xBF, 0x05, 0xA7, 0xBE, 0x3A, 0x3F, 0x7C, 0x28,
1782+
0x15, 0x12, 0x89, 0xDE, 0x5B, 0xB3, 0x64, 0x4D, 0x70, 0x11,
1783+
0x76, 0x1D, 0xB5, 0x6F, 0x2A, 0x03, 0x62, 0xFB, 0xA6, 0x4F,
1784+
0x98, 0xE6, 0x4F, 0xF9, 0x86, 0xDC, 0x4F, 0xB8, 0xEF, 0xDB,
1785+
0x2D, 0x6B, 0x8D, 0xA5, 0x71, 0x42, 0xA0, 0x07, 0x06, 0x05,
1786+
0x2B, 0x81, 0x04, 0x00, 0x22, 0xA1, 0x64, 0x03, 0x62, 0x00,
1787+
0x04, 0x38, 0xD6, 0x2B, 0xE4, 0x18, 0xFF, 0x57, 0x3F, 0xD0,
1788+
0xE0, 0x20, 0xD4, 0x88, 0x76, 0xC4, 0xE1, 0x12, 0x1D, 0xFB,
1789+
0x2D, 0x6E, 0xBE, 0xE4, 0x89, 0x5D, 0x77, 0x24, 0x31, 0x6D,
1790+
0x46, 0xA2, 0x31, 0x05, 0x87, 0x3F, 0x29, 0x86, 0xD5, 0xC7,
1791+
0x12, 0x80, 0x3A, 0x6F, 0x47, 0x1A, 0xB8, 0x68, 0x50, 0xEB,
1792+
0x06, 0x3E, 0x10, 0x89, 0x61, 0x34, 0x9C, 0xF8, 0xB4, 0xC6,
1793+
0xA4, 0xCF, 0x5E, 0x97, 0xBD, 0x7E, 0x51, 0xE9, 0x75, 0xE3,
1794+
0xE9, 0x21, 0x72, 0x61, 0x50, 0x6E, 0xB9, 0xCF, 0x3C, 0x49,
1795+
0x3D, 0x3E, 0xB8, 0x8D, 0x46, 0x7B, 0x5F, 0x27, 0xEB, 0xAB,
1796+
0x21, 0x61, 0xC0, 0x00, 0x66, 0xFE, 0xBD
1797+
};
1798+
#endif /* WOLFSSH_NO_ECDSA_SHA2_NISTP384 */
1799+
1800+
#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP521
1801+
/* keys/server-key-ecc-521.der - P-521 RFC-5915 ECPrivateKey */
1802+
static const byte unitTestEcc521PrivKey[] = {
1803+
0x30, 0x81, 0xDC, 0x02, 0x01, 0x01, 0x04, 0x42, 0x00, 0x4C,
1804+
0xA4, 0xD8, 0x64, 0x28, 0xD9, 0x40, 0x0E, 0x7B, 0x2D, 0xF3,
1805+
0x91, 0x2E, 0xB9, 0x96, 0xC1, 0x95, 0x89, 0x50, 0x43, 0xAF,
1806+
0x92, 0xE8, 0x6D, 0xE7, 0x0A, 0xE4, 0xDF, 0x46, 0xF2, 0x2A,
1807+
0x29, 0x1A, 0x6B, 0xB2, 0x74, 0x8A, 0xAE, 0x82, 0x58, 0x0D,
1808+
0xF6, 0xC3, 0x9F, 0x49, 0xB3, 0xED, 0x82, 0xF1, 0x78, 0x9E,
1809+
0xCE, 0x1B, 0x65, 0x7D, 0x45, 0x43, 0x8C, 0xFF, 0x15, 0x65,
1810+
0x34, 0x35, 0x45, 0x75, 0xA0, 0x07, 0x06, 0x05, 0x2B, 0x81,
1811+
0x04, 0x00, 0x23, 0xA1, 0x81, 0x89, 0x03, 0x81, 0x86, 0x00,
1812+
0x04, 0x01, 0xF8, 0xD0, 0xA7, 0xC3, 0xC5, 0x8D, 0x84, 0x19,
1813+
0x57, 0x96, 0x9F, 0x21, 0x3A, 0x94, 0xF3, 0xDA, 0x55, 0x0E,
1814+
0xDF, 0x76, 0xD8, 0xDD, 0x17, 0x15, 0x31, 0xF3, 0x5B, 0xB0,
1815+
0x69, 0xC8, 0xBC, 0x30, 0x0D, 0x6F, 0x6B, 0x37, 0xD1, 0x80,
1816+
0x46, 0xA9, 0x71, 0x7F, 0x2C, 0x6F, 0x59, 0x51, 0x9C, 0x82,
1817+
0x70, 0x95, 0xB2, 0x9A, 0x63, 0x13, 0x30, 0x62, 0x18, 0xC2,
1818+
0x35, 0x76, 0x94, 0x00, 0xD0, 0xF9, 0x6D, 0x00, 0x0A, 0x19,
1819+
0x3B, 0xA3, 0x46, 0x65, 0x2B, 0xEB, 0x40, 0x9A, 0x9A, 0x45,
1820+
0xC5, 0x97, 0xA3, 0xED, 0x93, 0x2D, 0xD5, 0xAA, 0xAE, 0x96,
1821+
0xBF, 0x2F, 0x31, 0x7E, 0x5A, 0x7A, 0xC7, 0x45, 0x8B, 0x3C,
1822+
0x6C, 0xDB, 0xAA, 0x90, 0xC3, 0x55, 0x38, 0x2C, 0xDF, 0xCD,
1823+
0xCA, 0x73, 0x77, 0xD9, 0x2E, 0xB2, 0x0A, 0x5E, 0x8C, 0x74,
1824+
0x23, 0x7C, 0xA5, 0xA3, 0x45, 0xB1, 0x9E, 0x3F, 0x1A, 0x22,
1825+
0x90, 0xB1, 0x54
1826+
};
1827+
#endif /* WOLFSSH_NO_ECDSA_SHA2_NISTP521 */
1828+
1829+
#if !defined(WOLFSSH_NO_ED25519)
1830+
/* keys/server-key-ed25519.der - Ed25519 OneAsymmetricKey (RFC 8410) */
1831+
static const byte unitTestEd25519PrivKey[] = {
1832+
0x30, 0x50, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b,
1833+
0x65, 0x70, 0x04, 0x22, 0x04, 0x20, 0x6a, 0x67, 0xf3, 0x0e,
1834+
0x64, 0xea, 0x52, 0xfe, 0xf4, 0xad, 0x65, 0x4d, 0x45, 0x60,
1835+
0x61, 0x38, 0x58, 0x11, 0x07, 0x84, 0xf0, 0x03, 0x94, 0x93,
1836+
0x14, 0x7b, 0x7b, 0x33, 0x1a, 0xba, 0xf6, 0x19, 0x81, 0x20,
1837+
0x0f, 0x56, 0x0c, 0x9f, 0x7d, 0x7a, 0x62, 0x87, 0xf0, 0x26,
1838+
0x16, 0x19, 0x31, 0xe4, 0xb2, 0x1d, 0xe9, 0xbd, 0xee, 0x4a,
1839+
0x7f, 0x55, 0xae, 0x26, 0x2d, 0xa1, 0x25, 0xe4, 0xee, 0x4a,
1840+
0x51, 0x00
1841+
};
1842+
#endif /* !WOLFSSH_NO_ED25519 */
1843+
1844+
#ifndef WOLFSSH_NO_ECDSA
1845+
/* P-256 DER with the OID last byte changed 0x07 -> 0x01 (secp192r1).
1846+
* Forces wc_EccPrivateKeyDecode to fail or to return an unsupported curve id,
1847+
* exercising the wc_ecc_free cleanup in both the default: and else paths. */
1848+
static const byte unitTestEccUnsupportedCurveKey[] = {
1849+
0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x61, 0x09, 0x99,
1850+
0x0B, 0x79, 0xD2, 0x5F, 0x28, 0x5A, 0x0F, 0x5D, 0x15, 0xCC,
1851+
0xA1, 0x56, 0x54, 0xF9, 0x2B, 0x39, 0x87, 0x21, 0x2D, 0xA7,
1852+
0x7D, 0x85, 0x7B, 0xB8, 0x7F, 0x38, 0xC6, 0x6D, 0xD5, 0xA0,
1853+
0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01,
1854+
0x01, /* 0x07 (secp256r1) changed to 0x01 (secp192r1) */
1855+
0xA1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x81, 0x13, 0xFF,
1856+
0xA4, 0x2B, 0xB7, 0x9C, 0x45, 0x74, 0x7A, 0x83, 0x4C, 0x61,
1857+
0xF3, 0x3F, 0xAD, 0x26, 0xCF, 0x22, 0xCD, 0xA9, 0xA3, 0xBC,
1858+
0xA5, 0x61, 0xB4, 0x7C, 0xE6, 0x62, 0xD4, 0xC2, 0xF7, 0x55,
1859+
0x43, 0x9A, 0x31, 0xFB, 0x80, 0x11, 0x20, 0xB5, 0x12, 0x4B,
1860+
0x24, 0xF5, 0x78, 0xD7, 0xFD, 0x22, 0xEF, 0x46, 0x35, 0xF0,
1861+
0x05, 0x58, 0x6B, 0x5F, 0x63, 0xC8, 0xDA, 0x1B, 0xC4, 0xF5,
1862+
0x69
1863+
};
1864+
#endif /* WOLFSSH_NO_ECDSA */
17531865

1866+
#ifndef WOLFSSH_NO_RSA
17541867
/* wolfSSH_RsaVerify unit test
17551868
*
17561869
* Verifies that wolfSSH_RsaVerify returns WS_RSA_E when given a signature
@@ -2034,6 +2147,98 @@ static int test_DoUserAuthRequestEd25519(void)
20342147

20352148
#endif /* Ed25519 verify test guards */
20362149

2150+
/* IdentifyAsn1Key unit test
2151+
*
2152+
* Exercises every new wc_Free* error-path added in IdentifyAsn1Key:
2153+
* - wc_FreeRsaKey on RSA decode failure
2154+
* - wc_ecc_free on ECC decode failure
2155+
* - wc_ecc_free in the default: branch (unsupported curve)
2156+
* - wc_ed25519_free on Ed25519 decode failure
2157+
* Each happy-path call implicitly exercises the failure-path frees for the
2158+
* other key types.
2159+
*/
2160+
static int test_IdentifyAsn1Key(void)
2161+
{
2162+
int result = 0;
2163+
int ret;
2164+
2165+
#ifndef WOLFSSH_NO_RSA
2166+
ret = IdentifyAsn1Key(unitTestRsaPrivKey, unitTestRsaPrivKeySz,
2167+
1, NULL, NULL);
2168+
if (ret != ID_SSH_RSA) {
2169+
printf("IdentifyAsn1Key: RSA priv failed, ret=%d\n", ret);
2170+
result = -600; goto done;
2171+
}
2172+
#endif
2173+
2174+
#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256
2175+
ret = IdentifyAsn1Key(unitTestEcc256PrivKey,
2176+
(word32)sizeof(unitTestEcc256PrivKey),
2177+
1, NULL, NULL);
2178+
if (ret != ID_ECDSA_SHA2_NISTP256) {
2179+
printf("IdentifyAsn1Key: ECC P-256 priv failed, ret=%d\n", ret);
2180+
result = -601; goto done;
2181+
}
2182+
#endif
2183+
2184+
#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP384
2185+
ret = IdentifyAsn1Key(unitTestEcc384PrivKey,
2186+
(word32)sizeof(unitTestEcc384PrivKey),
2187+
1, NULL, NULL);
2188+
if (ret != ID_ECDSA_SHA2_NISTP384) {
2189+
printf("IdentifyAsn1Key: ECC P-384 priv failed, ret=%d\n", ret);
2190+
result = -602; goto done;
2191+
}
2192+
#endif
2193+
2194+
#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP521
2195+
ret = IdentifyAsn1Key(unitTestEcc521PrivKey,
2196+
(word32)sizeof(unitTestEcc521PrivKey),
2197+
1, NULL, NULL);
2198+
if (ret != ID_ECDSA_SHA2_NISTP521) {
2199+
printf("IdentifyAsn1Key: ECC P-521 priv failed, ret=%d\n", ret);
2200+
result = -603; goto done;
2201+
}
2202+
#endif
2203+
2204+
#if !defined(WOLFSSH_NO_ED25519)
2205+
ret = IdentifyAsn1Key(unitTestEd25519PrivKey,
2206+
(word32)sizeof(unitTestEd25519PrivKey),
2207+
1, NULL, NULL);
2208+
if (ret != ID_ED25519) {
2209+
printf("IdentifyAsn1Key: Ed25519 priv failed, ret=%d\n", ret);
2210+
result = -604; goto done;
2211+
}
2212+
#endif
2213+
2214+
/* Unsupported ECC curve: triggers wc_ecc_free in the default: branch
2215+
* (wolfSSL has P-192) or the else branch (wolfSSL lacks P-192).
2216+
* Either way the key must be freed and WS_UNIMPLEMENTED_E returned. */
2217+
#ifndef WOLFSSH_NO_ECDSA
2218+
ret = IdentifyAsn1Key(unitTestEccUnsupportedCurveKey,
2219+
(word32)sizeof(unitTestEccUnsupportedCurveKey),
2220+
1, NULL, NULL);
2221+
if (ret != WS_UNIMPLEMENTED_E) {
2222+
printf("IdentifyAsn1Key: unsupported ECC curve expected "
2223+
"WS_UNIMPLEMENTED_E, got %d\n", ret);
2224+
result = -605; goto done;
2225+
}
2226+
#endif
2227+
2228+
/* Garbage: all decode attempts fail, all wc_Free* cleanup paths hit */
2229+
{
2230+
static const byte garbage[] = {0x00, 0x01, 0x02, 0x03};
2231+
ret = IdentifyAsn1Key(garbage, (word32)sizeof(garbage), 1, NULL, NULL);
2232+
if (ret != WS_UNIMPLEMENTED_E) {
2233+
printf("IdentifyAsn1Key: garbage expected WS_UNIMPLEMENTED_E, "
2234+
"got %d\n", ret);
2235+
result = -606; goto done;
2236+
}
2237+
}
2238+
2239+
done:
2240+
return result;
2241+
}
20372242
#endif /* WOLFSSH_TEST_INTERNAL */
20382243

20392244
/* Error Code And Message Test */
@@ -2165,6 +2370,10 @@ int wolfSSH_UnitTest(int argc, char** argv)
21652370
(unitResult == 0 ? "SUCCESS" : "FAILED"));
21662371
testResult = testResult || unitResult;
21672372

2373+
unitResult = test_IdentifyAsn1Key();
2374+
printf("IdentifyAsn1Key: %s\n", (unitResult == 0 ? "SUCCESS" : "FAILED"));
2375+
testResult = testResult || unitResult;
2376+
21682377
#endif
21692378

21702379
#ifdef WOLFSSH_KEYGEN

0 commit comments

Comments
 (0)