Skip to content
Open
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
10 changes: 10 additions & 0 deletions apps/wolfsshd/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -2049,6 +2049,16 @@ static int SetDefaultUserID(WOLFSSHD_AUTH* auth)
}

pwInfo = getpwnam(WOLFSSH_USER_STRING(WOLFSSH_SSHD_USER));
#ifdef WOLFSSHD_UNIT_TEST
/* Unit tests run wolfSSHD_AuthCreateUser() outside of a real daemon
* install, where the dedicated "sshd" system account may not exist.
* Fall back to the invoking user so auth-flow tests can exercise
* wolfSSHD_AuthCreateUser() without requiring that account. Never
* enabled in a production build. */
if (pwInfo == NULL) {
pwInfo = getpwuid(getuid());
}
#endif
if (pwInfo == NULL) {
/* user name not found on system */
wolfSSH_Log(WS_LOG_INFO, "[SSHD] No %s user found to use",
Expand Down
7 changes: 7 additions & 0 deletions apps/wolfsshd/test/start_sshd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ stop_wolfsshd() {
printf "Stopping SSHD, killing pid $PID\n"
sudo kill $PID

# Wait for the process to actually exit so a subsequent start_wolfsshd on
# the same port doesn't race the listening socket's release (EADDRINUSE).
for i in $(seq 1 50); do
sudo kill -0 $PID 2>/dev/null || break
sleep 0.1
done

# The temp dir is owned by the invoking user, so its root-owned key copies
# can be removed without sudo.
if [ -n "$SSHD_KEYDIR" ]; then
Expand Down
35 changes: 22 additions & 13 deletions examples/tpmcertserver/tpmcertclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#define TPMCC_USER "jill"
#define TPMCC_PASSWORD "upthehill"
#define TPMCC_BUF_SZ 1024
#define TPMCC_DEFAULT_PORT 22222

static int TpmCcUserAuth(byte authType, WS_UserAuthData* authData, void* ctx)
{
Expand Down Expand Up @@ -70,23 +71,31 @@ static int TpmCcHostKeyCheck(const byte* pubKey, word32 pubKeySz, void* ctx)
static int TpmCcLoadFile(const char* file, byte* buf, word32* bufSz)
{
int ret = 0;
FILE* f = fopen(file, "rb");
size_t n;
int extra;
WFILE* f;
word32 fileSz;
word32 readSz;

if (f == NULL) {
if (WFOPEN(NULL, &f, file, "rb") != 0) {
ret = -1;
}
else {
n = fread(buf, 1, *bufSz, f);
/* If the buffer filled exactly, the file may be larger than the buffer;
* reject a truncated read rather than loading a partial certificate. */
extra = (n == (size_t)*bufSz) ? fgetc(f) : EOF;
fclose(f);
if (n == 0 || extra != EOF)
WFSEEK(NULL, f, 0, WSEEK_END);
fileSz = (word32)WFTELL(NULL, f);
WREWIND(NULL, f);

if (fileSz == 0 || fileSz > *bufSz) {
ret = -1;
else
*bufSz = (word32)n;
}
else {
readSz = (word32)WFREAD(NULL, buf, 1, fileSz, f);
if (readSz != fileSz) {
ret = -1;
}
else {
*bufSz = fileSz;
}
}
WFCLOSE(NULL, f);
}

return ret;
Expand All @@ -97,7 +106,7 @@ int main(int argc, char* argv[])
{
int ret;
int i;
word16 port = 22222;
word16 port = TPMCC_DEFAULT_PORT;
const char* host = "127.0.0.1";
const char* caFile = "tpm-server-cert.der";
WOLFSSH_CTX* ctx = NULL;
Expand Down
23 changes: 16 additions & 7 deletions examples/tpmcertserver/tpmcertserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#define TPMCS_KEY_AUTH "ThisIsMyKeyAuth"
#define TPMCS_CERT_MAX 2048
#define TPMCS_BUF_SZ 1024
#define TPMCS_DEFAULT_PORT 22222

static const char* certOutFile = "tpm-server-cert.der";

Expand Down Expand Up @@ -142,8 +143,16 @@ static int TpmCsMakeKeyAndCert(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
}

if (rc >= 0) {
*certDerSz = (word32)rc;
rc = 0;
/* wolfTPM2_CSR_Generate_ex returns the generated DER length on
* success; sanity-check it against the output buffer capacity
* before trusting it as the certificate size. */
if (rc == 0 || (word32)rc > *certDerSz) {
rc = BUFFER_E;
}
else {
*certDerSz = (word32)rc;
rc = 0;
}
}

/* The crypto callback is only needed to self-sign the certificate. Always
Expand Down Expand Up @@ -179,15 +188,15 @@ static int TpmCsMakeKeyAndCert(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
static int TpmCsWriteCert(const char* file, const byte* der, word32 derSz)
{
int ret = 0;
FILE* f = fopen(file, "wb");
WFILE* f;

if (f == NULL) {
if (WFOPEN(NULL, &f, file, "wb") != 0) {
ret = -1;
}
else {
if (fwrite(der, 1, derSz, f) != derSz)
if (WFWRITE(NULL, der, 1, derSz, f) != derSz)
ret = -1;
fclose(f);
WFCLOSE(NULL, f);
}

return ret;
Expand Down Expand Up @@ -232,7 +241,7 @@ int main(int argc, char* argv[])
{
int ret;
int useEcc = 1;
word16 port = 22222;
word16 port = TPMCS_DEFAULT_PORT;
int i;
WOLFTPM2_DEV dev;
WOLFTPM2_KEY hostKey;
Expand Down
65 changes: 55 additions & 10 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@
#endif
#include <wolfssl/wolfcrypt/curve25519.h>
#include <wolfssl/wolfcrypt/ed25519.h>
#ifdef WOLFSSH_CERTS
#include <wolfssl/wolfcrypt/error-crypt.h>
#endif
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/rsa.h>
#include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/hmac.h>
Expand Down Expand Up @@ -6285,6 +6283,26 @@ static void FreePubKey(struct wolfSSH_sigKeyBlock *p)
}


/* Returns non-zero when a wolfCrypt error code indicates a local fault
* (memory, RNG, hardware, initialisation) rather than a peer-driven
* rejection. Used by the key-agreement helpers to log local faults at
* ERROR while keeping peer-driven rejects at DEBUG to prevent a remote
* peer from flooding the error log. */
static WS_MAYBE_UNUSED int IsLocalCryptoFault(int wcRet)
{
switch (wcRet) {
case MEMORY_E:
case RNG_FAILURE_E:
case WC_HW_E:
case WC_INIT_E:
case BAD_MUTEX_E:
return 1;
default:
return 0;
}
}


/* KeyAgreeDh_client
* hashId - wolfCrypt hash type ID used
* f - peer public key
Expand Down Expand Up @@ -6318,7 +6336,10 @@ static int KeyAgreeDh_client(WOLFSSH* ssh, byte hashId,
f, fSz);
PRIVATE_KEY_LOCK();
if (ret != 0) {
WLOG(WS_LOG_ERROR,
/* Local faults (RNG, HSM, memory) are logged at ERROR;
* peer-driven rejects stay at DEBUG so a remote peer
* cannot flood the error log. */
WLOG(IsLocalCryptoFault(ret) ? WS_LOG_ERROR : WS_LOG_DEBUG,
"Generate DH shared secret failed, %d", ret);
ret = WS_CRYPTO_FAILED;
}
Expand Down Expand Up @@ -6410,7 +6431,10 @@ static int KeyAgreeEcdh_client(WOLFSSH* ssh, byte hashId,
key_ptr, ssh->k, &ssh->kSz);
PRIVATE_KEY_LOCK();
if (ret != 0) {
WLOG(WS_LOG_ERROR,
/* Local faults (RNG, HSM, memory) are logged at ERROR;
* peer-driven rejects stay at DEBUG so a remote peer
* cannot flood the error log. */
WLOG(IsLocalCryptoFault(ret) ? WS_LOG_ERROR : WS_LOG_DEBUG,
"Generate ECC shared secret failed, %d", ret);
ret = WS_CRYPTO_FAILED;
}
Expand Down Expand Up @@ -6470,7 +6494,10 @@ static int KeyAgreeCurve25519_client(WOLFSSH* ssh, byte hashId,
ssh->k, &ssh->kSz, EC25519_LITTLE_ENDIAN);
PRIVATE_KEY_LOCK();
if (ret != 0) {
WLOG(WS_LOG_ERROR,
/* Local faults (RNG, HSM, memory) are logged at ERROR;
* peer-driven rejects stay at DEBUG so a remote peer
* cannot flood the error log. */
WLOG(IsLocalCryptoFault(ret) ? WS_LOG_ERROR : WS_LOG_DEBUG,
"Gen curve25519 shared secret failed, %d", ret);
ret = WS_CRYPTO_FAILED;
}
Expand Down Expand Up @@ -6679,7 +6706,10 @@ static int KeyAgreeEcdhMlKem_client(WOLFSSH* ssh, byte hashId,
ssh->kSz += length_sharedsecret;
} else {
ssh->kSz = 0;
WLOG(WS_LOG_ERROR,
/* Local faults (RNG, HSM, memory) are logged at ERROR;
* peer-driven rejects stay at DEBUG so a remote peer
* cannot flood the error log. */
WLOG(IsLocalCryptoFault(ret) ? WS_LOG_ERROR : WS_LOG_DEBUG,
"Generate ECC and ML-KEM (decap) shared secret failed, %d",
ret);
}
Expand Down Expand Up @@ -15922,9 +15952,18 @@ static int PrepareUserAuthRequestPassword(WOLFSSH* ssh, word32* payloadSz,
if (ssh == NULL || payloadSz == NULL || authData == NULL)
ret = WS_BAD_ARGUMENT;

if (ret == WS_SUCCESS)
*payloadSz += BOOLEAN_SZ + LENGTH_SZ +
authData->sf.password.passwordSz;
if (ret == WS_SUCCESS) {
word32 addSz = BOOLEAN_SZ + LENGTH_SZ;
if (MAX_PACKET_SZ < *payloadSz ||
MAX_PACKET_SZ - *payloadSz < addSz ||
MAX_PACKET_SZ - *payloadSz - addSz <
authData->sf.password.passwordSz) {
ret = WS_BUFFER_E;
}
else {
*payloadSz += addSz + authData->sf.password.passwordSz;
}
}

return ret;
}
Expand Down Expand Up @@ -20103,6 +20142,12 @@ int wolfSSH_TestDoUserAuthBanner(WOLFSSH* ssh, byte* buf, word32 len,
return DoUserAuthBanner(ssh, buf, len, idx);
}

int wolfSSH_TestPrepareUserAuthRequestPassword(WOLFSSH* ssh,
word32* payloadSz, const WS_UserAuthData* authData)
{
return PrepareUserAuthRequestPassword(ssh, payloadSz, authData);
}

int wolfSSH_TestDoChannelRequest(WOLFSSH* ssh, byte* buf, word32 len,
word32* idx)
{
Expand Down
38 changes: 29 additions & 9 deletions src/keygen.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,19 +276,33 @@ int wolfSSH_MakeMlDsaKey(byte* out, word32 outSz, word32 level)
}

if (ret == WS_SUCCESS) {
MlDsaKey key;
#ifdef WOLFSSH_SMALL_STACK
MlDsaKey* key;
#else
MlDsaKey keyBuf;
MlDsaKey* key = &keyBuf;
#endif
int keyInit = 0;

if (wc_MlDsaKey_Init(&key, NULL, INVALID_DEVID) != 0)
ret = WS_CRYPTO_FAILED;
else {
keyInit = 1;
if (wc_MlDsaKey_SetParams(&key, wc_level) != 0)
#ifdef WOLFSSH_SMALL_STACK
key = (MlDsaKey*)WMALLOC(sizeof(MlDsaKey), NULL, DYNTYPE_PRIVKEY);
if (key == NULL) {
ret = WS_MEMORY_E;
}
#endif

if (ret == WS_SUCCESS) {
if (wc_MlDsaKey_Init(key, NULL, INVALID_DEVID) != 0)
ret = WS_CRYPTO_FAILED;
else {
keyInit = 1;
if (wc_MlDsaKey_SetParams(key, wc_level) != 0)
ret = WS_CRYPTO_FAILED;
}
}

if (ret == WS_SUCCESS) {
ret = wc_MlDsaKey_MakeKey(&key, &rng);
ret = wc_MlDsaKey_MakeKey(key, &rng);
if (ret != 0) {
WLOG(WS_LOG_DEBUG, "ML-DSA key generation failed");
ret = WS_CRYPTO_FAILED;
Expand All @@ -300,7 +314,7 @@ int wolfSSH_MakeMlDsaKey(byte* out, word32 outSz, word32 level)
if (ret == WS_SUCCESS) {
int keySz;

keySz = wc_MlDsaKey_KeyToDer(&key, out, outSz);
keySz = wc_MlDsaKey_KeyToDer(key, out, outSz);
if (keySz < 0) {
WLOG(WS_LOG_DEBUG, "ML-DSA key to DER failed");
ret = WS_CRYPTO_FAILED;
Expand All @@ -310,9 +324,15 @@ int wolfSSH_MakeMlDsaKey(byte* out, word32 outSz, word32 level)
}

if (keyInit) {
wc_MlDsaKey_Free(&key);
wc_MlDsaKey_Free(key);
}

#ifdef WOLFSSH_SMALL_STACK
if (key != NULL) {
WFREE(key, NULL, DYNTYPE_PRIVKEY);
}
#endif

if (wc_FreeRng(&rng) != 0) {
WLOG(WS_LOG_DEBUG, "Couldn't free RNG");
if (ret >= 0)
Expand Down
Loading
Loading