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
20 changes: 15 additions & 5 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -1501,6 +1501,8 @@ int IdentifyAsn1Key(const byte* in, word32 inSz, int isPrivate, void* heap,
/* If decode was successful, this is an RSA key. */
if (ret == 0) {
key->keyId = ID_SSH_RSA;
} else {
wc_FreeRsaKey(&key->ks.rsa.key);
}
}
}
Expand Down Expand Up @@ -1533,7 +1535,12 @@ int IdentifyAsn1Key(const byte* in, word32 inSz, int isPrivate, void* heap,
case ECC_SECP521R1:
key->keyId = ID_ECDSA_SHA2_NISTP521;
break;
default:
/* Not a supported curve, so free the key */
wc_ecc_free(&key->ks.ecc.key);
}
} else {
wc_ecc_free(&key->ks.ecc.key);
}
}
}
Expand All @@ -1552,11 +1559,14 @@ int IdentifyAsn1Key(const byte* in, word32 inSz, int isPrivate, void* heap,
ret = wc_Ed25519PublicKeyDecode(in, &idx,
&key->ks.ed25519.key, inSz);
}
}

/* If decode was successful, this is a Ed25519 key. */
if (ret == 0)
key->keyId = ID_ED25519;
/* If decode was successful, this is a Ed25519 key. */
if (ret == 0) {
key->keyId = ID_ED25519;
} else {
wc_ed25519_free(&key->ks.ed25519.key);
}
}
}
#endif /* WOLFSSH_NO_ED25519 */

Expand Down Expand Up @@ -13050,7 +13060,7 @@ int SendKexDhReply(WOLFSSH* ssh)
else if (useEcc) {
ret = KeyAgreeEcdh_server(ssh, hashId, f_ptr, &fSz);
}
if (useCurve25519) {
else if (useCurve25519) {
ret = KeyAgreeCurve25519_server(ssh, hashId, f_ptr, &fSz);
}
else if (useEccMlKem) {
Expand Down
3 changes: 2 additions & 1 deletion src/wolfsftp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2775,7 +2775,6 @@ static int SFTP_CreateLongName(WS_SFTPNAME* name)

name->lName = (char*)WMALLOC(totalSz + 1, name->heap, DYNTYPE_SFTP);
if (name->lName == NULL) {
WFREE(name->lName, name->heap, DYNTYPE_SFTP);
return WS_MEMORY_E;
}
name->lSz = totalSz;
Expand Down Expand Up @@ -3987,6 +3986,7 @@ int wolfSSH_SFTP_RecvRead(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
if (res != NULL) {
if (wolfSSH_SFTP_CreateStatus(ssh, type, reqId, res, "English", NULL,
&outSz) != WS_SIZE_ONLY) {
WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER);
Comment thread
yosuke-wolfssl marked this conversation as resolved.
return WS_FATAL_ERROR;
}
if (outSz > strSz) {
Expand Down Expand Up @@ -5282,6 +5282,7 @@ int wolfSSH_SFTP_RecvFSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
if (ret == WS_SUCCESS) {
if (SFTP_SetHeader(ssh, reqId, WOLFSSH_FTP_ATTRS, sz, out)
!= WS_SUCCESS) {
WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER);
return WS_FATAL_ERROR;
}
SFTP_SetAttributes(ssh, out + WOLFSSH_SFTP_HEADER, sz, &atr);
Expand Down
211 changes: 210 additions & 1 deletion tests/unit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1485,7 +1485,7 @@ static int CaptureIoSendAuthSvc(WOLFSSH* ssh, void* buf, word32 sz, void* ctx)
*
* For invalid-service cases the auth-method field is intentionally omitted
* from the payload. DoUserAuthRequest must short-circuit at the service-name
* check and still satisfy all three assertions proving it never tries to
* check and still satisfy all three assertions - proving it never tries to
* parse the missing auth-method field. If the short-circuit were absent,
* GetSize() for authNameSz would hit end-of-buffer and return WS_BUFFER_E,
* failing assertion 1.
Expand Down Expand Up @@ -1750,7 +1750,120 @@ static const byte unitTestRsaPrivKey[] = {
};
static const word32 unitTestRsaPrivKeySz =
(word32)sizeof(unitTestRsaPrivKey);
#endif /* WOLFSSH_NO_RSA */

/* Keys for test_IdentifyAsn1Key: inline DER so the test is self-contained
* in both filesystem and NO_FILESYSTEM builds. Each array matches the
* corresponding file under keys/. */
#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256
/* keys/server-key-ecc.der - P-256 RFC-5915 ECPrivateKey */
static const byte unitTestEcc256PrivKey[] = {
0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x61, 0x09, 0x99,
0x0B, 0x79, 0xD2, 0x5F, 0x28, 0x5A, 0x0F, 0x5D, 0x15, 0xCC,
0xA1, 0x56, 0x54, 0xF9, 0x2B, 0x39, 0x87, 0x21, 0x2D, 0xA7,
0x7D, 0x85, 0x7B, 0xB8, 0x7F, 0x38, 0xC6, 0x6D, 0xD5, 0xA0,
0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01,
0x07, 0xA1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x81, 0x13, 0xFF,
0xA4, 0x2B, 0xB7, 0x9C, 0x45, 0x74, 0x7A, 0x83, 0x4C, 0x61,
0xF3, 0x3F, 0xAD, 0x26, 0xCF, 0x22, 0xCD, 0xA9, 0xA3, 0xBC,
0xA5, 0x61, 0xB4, 0x7C, 0xE6, 0x62, 0xD4, 0xC2, 0xF7, 0x55,
0x43, 0x9A, 0x31, 0xFB, 0x80, 0x11, 0x20, 0xB5, 0x12, 0x4B,
0x24, 0xF5, 0x78, 0xD7, 0xFD, 0x22, 0xEF, 0x46, 0x35, 0xF0,
0x05, 0x58, 0x6B, 0x5F, 0x63, 0xC8, 0xDA, 0x1B, 0xC4, 0xF5,
0x69
};
#endif /* WOLFSSH_NO_ECDSA_SHA2_NISTP256 */

#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP384
/* keys/server-key-ecc-384.der - P-384 RFC-5915 ECPrivateKey */
static const byte unitTestEcc384PrivKey[] = {
0x30, 0x81, 0xA4, 0x02, 0x01, 0x01, 0x04, 0x30, 0x3E, 0xAD,
0xD2, 0xBB, 0xBF, 0x05, 0xA7, 0xBE, 0x3A, 0x3F, 0x7C, 0x28,
0x15, 0x12, 0x89, 0xDE, 0x5B, 0xB3, 0x64, 0x4D, 0x70, 0x11,
0x76, 0x1D, 0xB5, 0x6F, 0x2A, 0x03, 0x62, 0xFB, 0xA6, 0x4F,
0x98, 0xE6, 0x4F, 0xF9, 0x86, 0xDC, 0x4F, 0xB8, 0xEF, 0xDB,
0x2D, 0x6B, 0x8D, 0xA5, 0x71, 0x42, 0xA0, 0x07, 0x06, 0x05,
0x2B, 0x81, 0x04, 0x00, 0x22, 0xA1, 0x64, 0x03, 0x62, 0x00,
0x04, 0x38, 0xD6, 0x2B, 0xE4, 0x18, 0xFF, 0x57, 0x3F, 0xD0,
0xE0, 0x20, 0xD4, 0x88, 0x76, 0xC4, 0xE1, 0x12, 0x1D, 0xFB,
0x2D, 0x6E, 0xBE, 0xE4, 0x89, 0x5D, 0x77, 0x24, 0x31, 0x6D,
0x46, 0xA2, 0x31, 0x05, 0x87, 0x3F, 0x29, 0x86, 0xD5, 0xC7,
0x12, 0x80, 0x3A, 0x6F, 0x47, 0x1A, 0xB8, 0x68, 0x50, 0xEB,
0x06, 0x3E, 0x10, 0x89, 0x61, 0x34, 0x9C, 0xF8, 0xB4, 0xC6,
0xA4, 0xCF, 0x5E, 0x97, 0xBD, 0x7E, 0x51, 0xE9, 0x75, 0xE3,
0xE9, 0x21, 0x72, 0x61, 0x50, 0x6E, 0xB9, 0xCF, 0x3C, 0x49,
0x3D, 0x3E, 0xB8, 0x8D, 0x46, 0x7B, 0x5F, 0x27, 0xEB, 0xAB,
0x21, 0x61, 0xC0, 0x00, 0x66, 0xFE, 0xBD
};
#endif /* WOLFSSH_NO_ECDSA_SHA2_NISTP384 */

#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP521
/* keys/server-key-ecc-521.der - P-521 RFC-5915 ECPrivateKey */
static const byte unitTestEcc521PrivKey[] = {
0x30, 0x81, 0xDC, 0x02, 0x01, 0x01, 0x04, 0x42, 0x00, 0x4C,
0xA4, 0xD8, 0x64, 0x28, 0xD9, 0x40, 0x0E, 0x7B, 0x2D, 0xF3,
0x91, 0x2E, 0xB9, 0x96, 0xC1, 0x95, 0x89, 0x50, 0x43, 0xAF,
0x92, 0xE8, 0x6D, 0xE7, 0x0A, 0xE4, 0xDF, 0x46, 0xF2, 0x2A,
0x29, 0x1A, 0x6B, 0xB2, 0x74, 0x8A, 0xAE, 0x82, 0x58, 0x0D,
0xF6, 0xC3, 0x9F, 0x49, 0xB3, 0xED, 0x82, 0xF1, 0x78, 0x9E,
0xCE, 0x1B, 0x65, 0x7D, 0x45, 0x43, 0x8C, 0xFF, 0x15, 0x65,
0x34, 0x35, 0x45, 0x75, 0xA0, 0x07, 0x06, 0x05, 0x2B, 0x81,
0x04, 0x00, 0x23, 0xA1, 0x81, 0x89, 0x03, 0x81, 0x86, 0x00,
0x04, 0x01, 0xF8, 0xD0, 0xA7, 0xC3, 0xC5, 0x8D, 0x84, 0x19,
0x57, 0x96, 0x9F, 0x21, 0x3A, 0x94, 0xF3, 0xDA, 0x55, 0x0E,
0xDF, 0x76, 0xD8, 0xDD, 0x17, 0x15, 0x31, 0xF3, 0x5B, 0xB0,
0x69, 0xC8, 0xBC, 0x30, 0x0D, 0x6F, 0x6B, 0x37, 0xD1, 0x80,
0x46, 0xA9, 0x71, 0x7F, 0x2C, 0x6F, 0x59, 0x51, 0x9C, 0x82,
0x70, 0x95, 0xB2, 0x9A, 0x63, 0x13, 0x30, 0x62, 0x18, 0xC2,
0x35, 0x76, 0x94, 0x00, 0xD0, 0xF9, 0x6D, 0x00, 0x0A, 0x19,
0x3B, 0xA3, 0x46, 0x65, 0x2B, 0xEB, 0x40, 0x9A, 0x9A, 0x45,
0xC5, 0x97, 0xA3, 0xED, 0x93, 0x2D, 0xD5, 0xAA, 0xAE, 0x96,
0xBF, 0x2F, 0x31, 0x7E, 0x5A, 0x7A, 0xC7, 0x45, 0x8B, 0x3C,
0x6C, 0xDB, 0xAA, 0x90, 0xC3, 0x55, 0x38, 0x2C, 0xDF, 0xCD,
0xCA, 0x73, 0x77, 0xD9, 0x2E, 0xB2, 0x0A, 0x5E, 0x8C, 0x74,
0x23, 0x7C, 0xA5, 0xA3, 0x45, 0xB1, 0x9E, 0x3F, 0x1A, 0x22,
0x90, 0xB1, 0x54
};
#endif /* WOLFSSH_NO_ECDSA_SHA2_NISTP521 */

#if !defined(WOLFSSH_NO_ED25519)
/* keys/server-key-ed25519.der - Ed25519 OneAsymmetricKey (RFC 8410) */
static const byte unitTestEd25519PrivKey[] = {
0x30, 0x50, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b,
0x65, 0x70, 0x04, 0x22, 0x04, 0x20, 0x6a, 0x67, 0xf3, 0x0e,
0x64, 0xea, 0x52, 0xfe, 0xf4, 0xad, 0x65, 0x4d, 0x45, 0x60,
0x61, 0x38, 0x58, 0x11, 0x07, 0x84, 0xf0, 0x03, 0x94, 0x93,
0x14, 0x7b, 0x7b, 0x33, 0x1a, 0xba, 0xf6, 0x19, 0x81, 0x20,
0x0f, 0x56, 0x0c, 0x9f, 0x7d, 0x7a, 0x62, 0x87, 0xf0, 0x26,
0x16, 0x19, 0x31, 0xe4, 0xb2, 0x1d, 0xe9, 0xbd, 0xee, 0x4a,
0x7f, 0x55, 0xae, 0x26, 0x2d, 0xa1, 0x25, 0xe4, 0xee, 0x4a,
0x51, 0x00
};
#endif /* !WOLFSSH_NO_ED25519 */

#ifndef WOLFSSH_NO_ECDSA
/* P-256 DER with the OID last byte changed 0x07 -> 0x01 (secp192r1).
* Forces wc_EccPrivateKeyDecode to fail or to return an unsupported curve id,
* exercising the wc_ecc_free cleanup in both the default: and else paths. */
static const byte unitTestEccUnsupportedCurveKey[] = {
0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x61, 0x09, 0x99,
0x0B, 0x79, 0xD2, 0x5F, 0x28, 0x5A, 0x0F, 0x5D, 0x15, 0xCC,
0xA1, 0x56, 0x54, 0xF9, 0x2B, 0x39, 0x87, 0x21, 0x2D, 0xA7,
0x7D, 0x85, 0x7B, 0xB8, 0x7F, 0x38, 0xC6, 0x6D, 0xD5, 0xA0,
0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01,
0x01, /* 0x07 (secp256r1) changed to 0x01 (secp192r1) */
0xA1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x81, 0x13, 0xFF,
0xA4, 0x2B, 0xB7, 0x9C, 0x45, 0x74, 0x7A, 0x83, 0x4C, 0x61,
0xF3, 0x3F, 0xAD, 0x26, 0xCF, 0x22, 0xCD, 0xA9, 0xA3, 0xBC,
0xA5, 0x61, 0xB4, 0x7C, 0xE6, 0x62, 0xD4, 0xC2, 0xF7, 0x55,
0x43, 0x9A, 0x31, 0xFB, 0x80, 0x11, 0x20, 0xB5, 0x12, 0x4B,
0x24, 0xF5, 0x78, 0xD7, 0xFD, 0x22, 0xEF, 0x46, 0x35, 0xF0,
0x05, 0x58, 0x6B, 0x5F, 0x63, 0xC8, 0xDA, 0x1B, 0xC4, 0xF5,
0x69
};
#endif /* WOLFSSH_NO_ECDSA */

#ifndef WOLFSSH_NO_RSA
/* wolfSSH_RsaVerify unit test
*
* Verifies that wolfSSH_RsaVerify returns WS_RSA_E when given a signature
Expand Down Expand Up @@ -2034,6 +2147,98 @@ static int test_DoUserAuthRequestEd25519(void)

#endif /* Ed25519 verify test guards */

/* IdentifyAsn1Key unit test
*
* Exercises every new wc_Free* error-path added in IdentifyAsn1Key:
* - wc_FreeRsaKey on RSA decode failure
* - wc_ecc_free on ECC decode failure
* - wc_ecc_free in the default: branch (unsupported curve)
* - wc_ed25519_free on Ed25519 decode failure
* Each happy-path call implicitly exercises the failure-path frees for the
* other key types.
*/
static int test_IdentifyAsn1Key(void)
{
int result = 0;
int ret;

#ifndef WOLFSSH_NO_RSA
ret = IdentifyAsn1Key(unitTestRsaPrivKey, unitTestRsaPrivKeySz,
1, NULL, NULL);
if (ret != ID_SSH_RSA) {
printf("IdentifyAsn1Key: RSA priv failed, ret=%d\n", ret);
result = -600; goto done;
}
#endif

#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256
ret = IdentifyAsn1Key(unitTestEcc256PrivKey,
(word32)sizeof(unitTestEcc256PrivKey),
1, NULL, NULL);
if (ret != ID_ECDSA_SHA2_NISTP256) {
printf("IdentifyAsn1Key: ECC P-256 priv failed, ret=%d\n", ret);
result = -601; goto done;
}
#endif

#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP384
ret = IdentifyAsn1Key(unitTestEcc384PrivKey,
(word32)sizeof(unitTestEcc384PrivKey),
1, NULL, NULL);
if (ret != ID_ECDSA_SHA2_NISTP384) {
printf("IdentifyAsn1Key: ECC P-384 priv failed, ret=%d\n", ret);
result = -602; goto done;
}
#endif

#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP521
ret = IdentifyAsn1Key(unitTestEcc521PrivKey,
(word32)sizeof(unitTestEcc521PrivKey),
1, NULL, NULL);
if (ret != ID_ECDSA_SHA2_NISTP521) {
printf("IdentifyAsn1Key: ECC P-521 priv failed, ret=%d\n", ret);
result = -603; goto done;
}
#endif

#if !defined(WOLFSSH_NO_ED25519)
ret = IdentifyAsn1Key(unitTestEd25519PrivKey,
(word32)sizeof(unitTestEd25519PrivKey),
1, NULL, NULL);
if (ret != ID_ED25519) {
printf("IdentifyAsn1Key: Ed25519 priv failed, ret=%d\n", ret);
result = -604; goto done;
}
#endif

/* Unsupported ECC curve: triggers wc_ecc_free in the default: branch
* (wolfSSL has P-192) or the else branch (wolfSSL lacks P-192).
* Either way the key must be freed and WS_UNIMPLEMENTED_E returned. */
#ifndef WOLFSSH_NO_ECDSA
ret = IdentifyAsn1Key(unitTestEccUnsupportedCurveKey,
(word32)sizeof(unitTestEccUnsupportedCurveKey),
1, NULL, NULL);
if (ret != WS_UNIMPLEMENTED_E) {
printf("IdentifyAsn1Key: unsupported ECC curve expected "
"WS_UNIMPLEMENTED_E, got %d\n", ret);
result = -605; goto done;
}
#endif

/* Garbage: all decode attempts fail, all wc_Free* cleanup paths hit */
{
static const byte garbage[] = {0x00, 0x01, 0x02, 0x03};
ret = IdentifyAsn1Key(garbage, (word32)sizeof(garbage), 1, NULL, NULL);
if (ret != WS_UNIMPLEMENTED_E) {
printf("IdentifyAsn1Key: garbage expected WS_UNIMPLEMENTED_E, "
"got %d\n", ret);
result = -606; goto done;
}
}

done:
return result;
}
#endif /* WOLFSSH_TEST_INTERNAL */

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

unitResult = test_IdentifyAsn1Key();
printf("IdentifyAsn1Key: %s\n", (unitResult == 0 ? "SUCCESS" : "FAILED"));
testResult = testResult || unitResult;

#endif

#ifdef WOLFSSH_KEYGEN
Expand Down
Loading