From 073afe140789bfaab5d25bc2f741ee2d9bf71266 Mon Sep 17 00:00:00 2001 From: Kareem Date: Wed, 1 Jul 2026 15:41:02 -0700 Subject: [PATCH 1/8] Add a segment-size bounds check before computing remaining buffer space in wolfSSH_RealPath. Reported-by: Asif Nadaf --- src/ssh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ssh.c b/src/ssh.c index f73754e92..fced01523 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -3835,7 +3835,7 @@ int wolfSSH_RealPath(const char* defaultPath, char* in, } /* Everything else is copied */ else { - if (curSz >= outSz - segSz) { + if (segSz > outSz || curSz >= outSz - segSz) { return WS_INVALID_PATH_E; } From 00168bb1a41d88d1212ae52096ca04f299908091 Mon Sep 17 00:00:00 2001 From: Kareem Date: Mon, 6 Jul 2026 10:35:54 -0700 Subject: [PATCH 2/8] Ensure the key blob size is correct in FindKeyId. Reported-by: Asif Nadaf --- src/agent.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/agent.c b/src/agent.c index 7b7ac5c5d..318b2b4f0 100644 --- a/src/agent.c +++ b/src/agent.c @@ -672,7 +672,8 @@ static WOLFSSH_AGENT_ID* FindKeyId(WOLFSSH_AGENT_ID* id, if (ret == WS_SUCCESS) { while (id != NULL && WMEMCMP(digest, id->id, WC_SHA256_DIGEST_SIZE) != 0 && - WMEMCMP(keyBlob, id->keyBlob, keyBlobSz)) { + (id->keyBlobSz != keyBlobSz || + WMEMCMP(keyBlob, id->keyBlob, id->keyBlobSz) != 0)) { id = id->next; } } From 27df501ff105b3a96d343ada8ac79ee4034ada48 Mon Sep 17 00:00:00 2001 From: Kareem Date: Mon, 6 Jul 2026 11:05:43 -0700 Subject: [PATCH 3/8] Fix multiple issues in PostLock/PostUnlock. Reported-by: Asif Nadaf --- src/agent.c | 56 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/src/agent.c b/src/agent.c index 318b2b4f0..30c855faf 100644 --- a/src/agent.c +++ b/src/agent.c @@ -370,22 +370,28 @@ static int PostSuccess(WOLFSSH_AGENT_CTX* agent) static int PostLock(WOLFSSH_AGENT_CTX* agent, const byte* passphrase, word32 passphraseSz) { - char pp[32]; - word32 ppSz; + char* pp; + int ret = WS_SUCCESS; - (void)agent; WLOG(WS_LOG_AGENT, "Posting lock to agent %p", agent); - WOLFSSH_UNUSED(agent); - ppSz = sizeof(pp) - 1; - if (passphraseSz < ppSz) - ppSz = passphraseSz; + pp = (char*)WMALLOC(passphraseSz + 1, agent->heap, DYNTYPE_STRING); + if (pp == NULL) + ret = WS_MEMORY_E; - WMEMCPY(pp, passphrase, ppSz); - pp[ppSz] = 0; - WLOG(WS_LOG_AGENT, "Locking with passphrase '%s'", pp); + if (ret == WS_SUCCESS) { + WMEMCPY(pp, passphrase, passphraseSz); + pp[passphraseSz] = 0; +#ifdef SHOW_SECRETS + WLOG(WS_LOG_AGENT, "Locking with passphrase '%s'", pp); +#else + WLOG(WS_LOG_AGENT, "Locking with passphrase"); +#endif + ForceZero(pp, passphraseSz); + WFREE(pp, agent->heap, DYNTYPE_STRING); + } - return WS_SUCCESS; + return ret; } @@ -393,22 +399,28 @@ static int PostLock(WOLFSSH_AGENT_CTX* agent, static int PostUnlock(WOLFSSH_AGENT_CTX* agent, const byte* passphrase, word32 passphraseSz) { - char pp[32]; - word32 ppSz; + char* pp; + int ret = WS_SUCCESS; - (void)agent; WLOG(WS_LOG_AGENT, "Posting unlock to agent %p", agent); - WOLFSSH_UNUSED(agent); - ppSz = sizeof(pp) - 1; - if (passphraseSz < ppSz) - ppSz = passphraseSz; + pp = (char*)WMALLOC(passphraseSz + 1, agent->heap, DYNTYPE_STRING); + if (pp == NULL) + ret = WS_MEMORY_E; - WMEMCPY(pp, passphrase, ppSz); - pp[ppSz] = 0; - WLOG(WS_LOG_AGENT, "Unlocking with passphrase '%s'", pp); + if (ret == WS_SUCCESS) { + WMEMCPY(pp, passphrase, passphraseSz); + pp[passphraseSz] = 0; +#ifdef SHOW_SECRETS + WLOG(WS_LOG_AGENT, "Unlocking with passphrase '%s'", pp); +#else + WLOG(WS_LOG_AGENT, "Unlocking with passphrase"); +#endif + ForceZero(pp, passphraseSz); + WFREE(pp, agent->heap, DYNTYPE_STRING); + } - return WS_SUCCESS; + return ret; } From 1695545cb64a74b2fd50f23319b3e6ab8772e1a6 Mon Sep 17 00:00:00 2001 From: Kareem Date: Mon, 6 Jul 2026 15:15:25 -0700 Subject: [PATCH 4/8] Replace atoi with strtoull in SCP code. Reported-by: Asif Nadaf --- src/wolfscp.c | 73 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 20 deletions(-) diff --git a/src/wolfscp.c b/src/wolfscp.c index c6ed7a54c..0900c7c3e 100644 --- a/src/wolfscp.c +++ b/src/wolfscp.c @@ -39,6 +39,9 @@ #include #include +#include +#include + #ifdef NO_INLINE #include @@ -1093,19 +1096,35 @@ static int GetScpFileSize(WOLFSSH* ssh, byte* buf, word32 bufSz, ret = WS_SCP_BAD_MSG_E; if (ret == WS_SUCCESS) { - /* replace space with newline for atoi */ - buf[spaceIdx] = '\n'; - ssh->scpFileSz = atoi((char *)(buf + idx)); + /* replace space with newline to terminate the size field, then parse + * with strtoull() which parses in 64-bit width, so a negative field + * such as "-1" wraps above UINT32_MAX and is rejected by the bound + * below instead of becoming a huge word32 size */ + char* endptr = NULL; + word64 fileSz; - /* restore space, increment idx to space */ + buf[spaceIdx] = '\n'; + errno = 0; + fileSz = (word64)strtoull((char*)(buf + idx), &endptr, 10); buf[spaceIdx] = ' '; - idx = spaceIdx; - /* eat trailing space */ - if (bufSz >= (word32)(idx + 1)) - idx++; + /* reject any parse error (e.g. ERANGE overflow), a non-numeric field + * (parse must consume every character up to the separator), and + * sizes too large for the word32 scpFileSz */ + if (errno != 0 || endptr != (char*)(buf + spaceIdx) || + fileSz > UINT32_MAX) { + ret = WS_SCP_BAD_MSG_E; + } + else { + ssh->scpFileSz = (word32)fileSz; - *inOutIdx = idx; + /* increment idx to space, then eat trailing space */ + idx = spaceIdx; + if (bufSz >= (word32)(idx + 1)) + idx++; + + *inOutIdx = idx; + } } return ret; @@ -1225,15 +1244,23 @@ static int GetScpTimestamp(WOLFSSH* ssh, byte* buf, word32 bufSz, /* read modification time */ if (ret == WS_SUCCESS) { - /* replace space with newline for atoi */ - buf[spaceIdx] = '\n'; - ssh->scpMTime = atoi((char*)(buf + idx)); + char* endptr = NULL; - /* restore space, increment idx past it */ + /* replace space with newline to terminate the field */ + buf[spaceIdx] = '\n'; + errno = 0; + ssh->scpMTime = (word64)strtoull((char*)(buf + idx), &endptr, 10); buf[spaceIdx] = ' '; - if (spaceIdx + 1 < bufSz) { + + /* reject any parse error (e.g. ERANGE overflow) and a non-numeric + * field, then step past the separating space */ + if (errno != 0 || endptr != (char*)(buf + spaceIdx)) { + ret = WS_SCP_TIMESTAMP_E; + } + else if (spaceIdx + 1 < bufSz) { idx = spaceIdx + 1; - } else { + } + else { ret = WS_SCP_TIMESTAMP_E; } } @@ -1264,15 +1291,21 @@ static int GetScpTimestamp(WOLFSSH* ssh, byte* buf, word32 bufSz, } if (ret == WS_SUCCESS) { - /* replace space with newline for atoi */ + char* endptr = NULL; + /* replace space with newline for strtoull */ buf[spaceIdx] = '\n'; - ssh->scpATime = atoi((char*)(buf + idx)); - + errno = 0; + ssh->scpATime = (word64)strtoull((char*)(buf + idx), &endptr, 10); /* restore space, increment idx past it */ buf[spaceIdx] = ' '; - if (spaceIdx + 1 < bufSz) { + + if (errno != 0 || endptr != (char*)(buf + spaceIdx)) { + ret = WS_SCP_TIMESTAMP_E; + } + else if (spaceIdx + 1 < bufSz) { idx = spaceIdx + 1; - } else { + } + else { ret = WS_SCP_TIMESTAMP_E; } } From 516659b6dd46b15737e89a908535288087dd211f Mon Sep 17 00:00:00 2001 From: Kareem Date: Mon, 6 Jul 2026 15:27:03 -0700 Subject: [PATCH 5/8] Add NULL check to wolfSSH_CERTMAN_LoadRootCA_buffer. Reported-by: Asif Nadaf --- src/certman.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/certman.c b/src/certman.c index 1352b37d0..3569895e8 100644 --- a/src/certman.c +++ b/src/certman.c @@ -174,14 +174,16 @@ void wolfSSH_CERTMAN_free(WOLFSSH_CERTMAN* cm) int wolfSSH_CERTMAN_LoadRootCA_buffer(WOLFSSH_CERTMAN* cm, const unsigned char* rootCa, word32 rootCaSz) { - int ret; + int ret = WS_BAD_ARGUMENT; WLOG_ENTER(); - ret = wolfSSL_CertManagerLoadCABuffer(cm->cm, rootCa, rootCaSz, - WOLFSSL_FILETYPE_ASN1); - if (ret == WOLFSSL_SUCCESS) { - ret = WS_SUCCESS; + if (cm != NULL) { + ret = wolfSSL_CertManagerLoadCABuffer(cm->cm, rootCa, rootCaSz, + WOLFSSL_FILETYPE_ASN1); + if (ret == WOLFSSL_SUCCESS) { + ret = WS_SUCCESS; + } } WLOG_LEAVE(ret); From 5fc31b5f2944ae22d27efe6fc0b2c09f6f07fb9b Mon Sep 17 00:00:00 2001 From: Kareem Date: Mon, 6 Jul 2026 15:32:30 -0700 Subject: [PATCH 6/8] Rework free space calculation in wstrncat. Reported-by: Asif Nadaf --- src/port.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/port.c b/src/port.c index 78814fd56..996ef4ef3 100644 --- a/src/port.c +++ b/src/port.c @@ -839,7 +839,14 @@ char* wstrnstr(const char* s1, const char* s2, unsigned int n) * end of s1 including a null terminator. */ char* wstrncat(char* s1, const char* s2, size_t n) { - size_t freeSpace = n - strlen(s1) - 1; + size_t s1_len = strlen(s1); + size_t freeSpace; + + if (s1_len >= n) { + return NULL; + } + + freeSpace = n - s1_len - 1; if (freeSpace >= strlen(s2)) { #ifndef USE_WINDOWS_API From 9fff58e4adeafaae7a693581365c4d6c8c1baa7f Mon Sep 17 00:00:00 2001 From: Kareem Date: Mon, 6 Jul 2026 16:47:45 -0700 Subject: [PATCH 7/8] Code review feedback --- src/agent.c | 11 +++++++++-- src/certman.c | 2 +- src/port.c | 6 +++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/agent.c b/src/agent.c index 30c855faf..85766fb21 100644 --- a/src/agent.c +++ b/src/agent.c @@ -61,6 +61,11 @@ #endif +#ifndef WOLFSSH_MAX_PASSPHRASE_SZ + #define WOLFSSH_MAX_PASSPHRASE_SZ 256 +#endif + + /* payloadSz is an estimate, but it shall be greater-than/equal-to * the actual value. */ static int PrepareMessage(WOLFSSH_AGENT_CTX* agent, word32 payloadSz) @@ -1265,7 +1270,8 @@ static int DoAgentLock(WOLFSSH_AGENT_CTX* agent, ato32(buf + begin, &passphraseSz); begin += LENGTH_SZ; - if (begin + passphraseSz > len) { + if (passphraseSz > WOLFSSH_MAX_PASSPHRASE_SZ || + begin + passphraseSz > len) { ret = WS_PARSE_E; } } @@ -1309,7 +1315,8 @@ static int DoAgentUnlock(WOLFSSH_AGENT_CTX* agent, ato32(buf + begin, &passphraseSz); begin += LENGTH_SZ; - if (begin + passphraseSz > len) + if (passphraseSz > WOLFSSH_MAX_PASSPHRASE_SZ || + begin + passphraseSz > len) ret = WS_PARSE_E; } diff --git a/src/certman.c b/src/certman.c index 3569895e8..e0bf154f9 100644 --- a/src/certman.c +++ b/src/certman.c @@ -178,7 +178,7 @@ int wolfSSH_CERTMAN_LoadRootCA_buffer(WOLFSSH_CERTMAN* cm, WLOG_ENTER(); - if (cm != NULL) { + if (cm != NULL && rootCa != NULL && rootCaSz > 0) { ret = wolfSSL_CertManagerLoadCABuffer(cm->cm, rootCa, rootCaSz, WOLFSSL_FILETYPE_ASN1); if (ret == WOLFSSL_SUCCESS) { diff --git a/src/port.c b/src/port.c index 996ef4ef3..8c1255a64 100644 --- a/src/port.c +++ b/src/port.c @@ -839,9 +839,13 @@ char* wstrnstr(const char* s1, const char* s2, unsigned int n) * end of s1 including a null terminator. */ char* wstrncat(char* s1, const char* s2, size_t n) { - size_t s1_len = strlen(s1); + size_t s1_len = 0; size_t freeSpace; + while (s1_len < n && s1[s1_len] != '\0') { + s1_len++; + } + if (s1_len >= n) { return NULL; } From 2d7dee68e8ccb051035d1aa40d54d1c1e6d0b1b6 Mon Sep 17 00:00:00 2001 From: Kareem Date: Wed, 15 Jul 2026 15:33:05 -0700 Subject: [PATCH 8/8] Code review feedback --- src/ssh.c | 17 +++++- src/wolfscp.c | 18 +++++- tests/unit.c | 143 +++++++++++++++++++++++++++++++++++++++++++++ wolfssh/internal.h | 4 ++ 4 files changed, 178 insertions(+), 4 deletions(-) diff --git a/src/ssh.c b/src/ssh.c index fced01523..4d8bd60b9 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -3835,15 +3835,26 @@ int wolfSSH_RealPath(const char* defaultPath, char* in, } /* Everything else is copied */ else { - if (segSz > outSz || curSz >= outSz - segSz) { + word32 sepSz = (curSz != 1) ? 1 : 0; + + /* Need room for the optional separator, the segment, and the + * terminating null. Guard the subtraction against underflow. */ + if (segSz >= outSz || curSz + sepSz >= outSz - segSz) { return WS_INVALID_PATH_E; } + /* Pass the full buffer size to WSTRNCAT: it measures the current + * contents itself and returns NULL if the append would not fit, + * so a truncated append is reported rather than silently kept. */ if (curSz != 1) { - WSTRNCAT(out, "/", outSz - curSz); + if (WSTRNCAT(out, "/", outSz) == NULL) { + return WS_INVALID_PATH_E; + } curSz++; } - WSTRNCAT(out, seg, outSz - curSz); + if (WSTRNCAT(out, seg, outSz) == NULL) { + return WS_INVALID_PATH_E; + } curSz += segSz; } } diff --git a/src/wolfscp.c b/src/wolfscp.c index 0900c7c3e..81b024aa7 100644 --- a/src/wolfscp.c +++ b/src/wolfscp.c @@ -1317,6 +1317,22 @@ static int GetScpTimestamp(WOLFSSH* ssh, byte* buf, word32 bufSz, return ret; } + +#ifdef WOLFSSH_TEST_INTERNAL +int wolfSSH_TestScpGetFileSize(WOLFSSH* ssh, byte* buf, word32 bufSz, + word32* inOutIdx) +{ + return GetScpFileSize(ssh, buf, bufSz, inOutIdx); +} + +int wolfSSH_TestScpGetTimestamp(WOLFSSH* ssh, byte* buf, word32 bufSz, + word32* inOutIdx) +{ + return GetScpTimestamp(ssh, buf, bufSz, inOutIdx); +} +#endif /* WOLFSSH_TEST_INTERNAL */ + + /* checks for if directory is being renamed in command * * returns WS_SUCCESS on success @@ -2463,7 +2479,7 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath, /* cd into directory */ #ifdef WOLFSSL_NUCLEUS - WSTRNCAT((char*)basePath, "/", sizeof("/")); + WSTRNCAT((char*)basePath, "/", WOLFSSH_MAX_FILENAME); WSTRNCAT((char*)basePath, fileName, WOLFSSH_MAX_FILENAME); wolfSSH_CleanPath(ssh, (char*)basePath, WOLFSSH_MAX_FILENAME); ssh->scpDirDepth++; diff --git a/tests/unit.c b/tests/unit.c index 6be8faed1..a85ce7259 100644 --- a/tests/unit.c +++ b/tests/unit.c @@ -1433,6 +1433,141 @@ static int test_ScpGetFileMode(void) wolfSSH_CTX_free(ctx); return result; } + +/* Drive GetScpFileSize directly, covering the strtoull()-based parsing added to + * replace atoi: valid sizes up to UINT32_MAX are accepted, while negative, + * out-of-range, and non-numeric fields are rejected instead of silently + * wrapping into a bogus word32 size. */ +static int test_ScpGetFileSize(void) +{ + WOLFSSH_CTX* ctx = NULL; + WOLFSSH* ssh = NULL; + static const char* good[] = { + "0 f\n", + "1024 file.txt\n", + "4294967295 f\n" /* UINT32_MAX, the largest accepted size */ + }; + static const word32 goodSz[] = { 0, 1024, 4294967295UL }; + static const char* bad[] = { + "-1 f\n", /* negative wraps above UINT32_MAX */ + "4294967296 f\n", /* one past UINT32_MAX */ + "18446744073709551616 f\n", /* overflows 64-bit width (ERANGE) */ + "12x34 f\n", /* trailing junk before the separator */ + "abc f\n" /* not numeric at all */ + }; + char tmp[48]; + int result = 0; + int ret; + int i; + word32 idx; + + ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL); + if (ctx == NULL) + return -430; + ssh = wolfSSH_new(ctx); + if (ssh == NULL) { + wolfSSH_CTX_free(ctx); + return -431; + } + + for (i = 0; i < (int)(sizeof(good) / sizeof(good[0])); i++) { + WMEMSET(tmp, 0, sizeof(tmp)); + WSTRNCPY(tmp, good[i], sizeof(tmp) - 1); + idx = 0; + ssh->scpFileSz = 0; + ret = wolfSSH_TestScpGetFileSize(ssh, (byte*)tmp, + (word32)WSTRLEN(tmp), &idx); + if (ret != WS_SUCCESS) { + result = -432; + break; + } + if (ssh->scpFileSz != goodSz[i]) { + result = -433; + break; + } + } + + for (i = 0; result == 0 && + i < (int)(sizeof(bad) / sizeof(bad[0])); i++) { + WMEMSET(tmp, 0, sizeof(tmp)); + WSTRNCPY(tmp, bad[i], sizeof(tmp) - 1); + idx = 0; + ret = wolfSSH_TestScpGetFileSize(ssh, (byte*)tmp, + (word32)WSTRLEN(tmp), &idx); + if (ret == WS_SUCCESS) { + result = -434; + break; + } + } + + wolfSSH_free(ssh); + wolfSSH_CTX_free(ctx); + return result; +} + +/* Drive GetScpTimestamp directly, covering the strtoull()-based parsing of the + * "T 0 0" record: a well-formed record populates both times, + * while a missing 'T', malformed separator, non-numeric field, and overflowing + * field are all rejected. */ +static int test_ScpGetTimestamp(void) +{ + WOLFSSH_CTX* ctx = NULL; + WOLFSSH* ssh = NULL; + static const char* bad[] = { + "1609459200 0 1609459200 0\n", /* missing leading 'T' */ + "T12x 0 100 0\n", /* mtime not fully numeric */ + "T99999999999999999999999999 0 100 0\n", /* mtime overflow (ERANGE) */ + "T100 5 100 0\n", /* mtime separator not "0 " */ + "T100 0 abc 0\n", /* atime not numeric */ + "T100 0 99999999999999999999999999 0\n" /* atime overflow (ERANGE) */ + }; + char tmp[64]; + int result = 0; + int ret; + int i; + word32 idx; + + ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL); + if (ctx == NULL) + return -440; + ssh = wolfSSH_new(ctx); + if (ssh == NULL) { + wolfSSH_CTX_free(ctx); + return -441; + } + + /* a valid record parses both the modification and access times */ + WMEMSET(tmp, 0, sizeof(tmp)); + WSTRNCPY(tmp, "T1609459200 0 1609459201 0\n", sizeof(tmp) - 1); + idx = 0; + ssh->scpMTime = 0; + ssh->scpATime = 0; + ret = wolfSSH_TestScpGetTimestamp(ssh, (byte*)tmp, + (word32)WSTRLEN(tmp), &idx); + if (ret != WS_SUCCESS) + result = -442; + else if (ssh->scpMTime != (word64)1609459200) + result = -443; + else if (ssh->scpATime != (word64)1609459201) + result = -444; + + for (i = 0; result == 0 && + i < (int)(sizeof(bad) / sizeof(bad[0])); i++) { + WMEMSET(tmp, 0, sizeof(tmp)); + WSTRNCPY(tmp, bad[i], sizeof(tmp) - 1); + idx = 0; + ret = wolfSSH_TestScpGetTimestamp(ssh, (byte*)tmp, + (word32)WSTRLEN(tmp), &idx); + if (ret == WS_SUCCESS) { + result = -445; + break; + } + } + + wolfSSH_free(ssh); + wolfSSH_CTX_free(ctx); + return result; +} #endif /* WOLFSSH_TEST_INTERNAL && WOLFSSH_SCP */ static int test_ChannelPutData(void) @@ -7867,6 +8002,14 @@ int wolfSSH_UnitTest(int argc, char** argv) unitResult = test_ScpGetFileMode(); printf("ScpGetFileMode: %s\n", (unitResult == 0 ? "SUCCESS" : "FAILED")); testResult = testResult || unitResult; + + unitResult = test_ScpGetFileSize(); + printf("ScpGetFileSize: %s\n", (unitResult == 0 ? "SUCCESS" : "FAILED")); + testResult = testResult || unitResult; + + unitResult = test_ScpGetTimestamp(); + printf("ScpGetTimestamp: %s\n", (unitResult == 0 ? "SUCCESS" : "FAILED")); + testResult = testResult || unitResult; #endif unitResult = test_MsgHighwater(); diff --git a/wolfssh/internal.h b/wolfssh/internal.h index dba5dbf32..5a1475ad4 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -1482,6 +1482,10 @@ enum WS_MessageIdLimits { #ifdef WOLFSSH_SCP WOLFSSH_API int wolfSSH_TestScpGetFileMode(WOLFSSH* ssh, byte* buf, word32 bufSz, word32* inOutIdx); + WOLFSSH_API int wolfSSH_TestScpGetFileSize(WOLFSSH* ssh, byte* buf, + word32 bufSz, word32* inOutIdx); + WOLFSSH_API int wolfSSH_TestScpGetTimestamp(WOLFSSH* ssh, byte* buf, + word32 bufSz, word32* inOutIdx); #endif /* WOLFSSH_SCP */ #ifndef WOLFSSH_NO_DH WOLFSSH_API int wolfSSH_TestKeyAgreeDh_client(WOLFSSH* ssh, byte hashId,