From b8e2fd3703fd24957cbd9ca67ccfbd6667523d24 Mon Sep 17 00:00:00 2001 From: aidan garske Date: Tue, 7 Jul 2026 12:23:55 -0700 Subject: [PATCH] Address review: TPM publickey auth fallback, reject truncated CA, guard negative CI test, silence maybe-uninitialized --- .github/workflows/tpm-ssh.yml | 6 ++++++ examples/tpmcertserver/tpmcertclient.c | 6 +++++- examples/tpmcertserver/tpmcertserver.c | 4 ++-- src/internal.c | 7 +++++-- wolfssh/internal.h | 3 +++ 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/.github/workflows/tpm-ssh.yml b/.github/workflows/tpm-ssh.yml index 0da94347..de34aa55 100644 --- a/.github/workflows/tpm-ssh.yml +++ b/.github/workflows/tpm-ssh.yml @@ -186,8 +186,14 @@ jobs: cat tpmcert_client_neg.txt exit 1 fi + echo "----- server -----"; cat tpmcert_server_neg.txt echo "client correctly rejected the untrusted server:" cat tpmcert_client_neg.txt + # Guard against a false pass: the server must have come up, and the + # client must have failed inside the SSH handshake (certificate + # rejection) rather than from a plain connection failure. + grep -q "Listening on port" tpmcert_server_neg.txt + grep -q "wolfSSH_connect failed" tpmcert_client_neg.txt # Client public-key authentication with a TPM-resident key (RSA only). - name: Test TPM client public-key auth diff --git a/examples/tpmcertserver/tpmcertclient.c b/examples/tpmcertserver/tpmcertclient.c index 4262017c..33defea6 100644 --- a/examples/tpmcertserver/tpmcertclient.c +++ b/examples/tpmcertserver/tpmcertclient.c @@ -72,14 +72,18 @@ static int TpmCcLoadFile(const char* file, byte* buf, word32* bufSz) int ret = 0; FILE* f = fopen(file, "rb"); size_t n; + int extra; if (f == NULL) { 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) + if (n == 0 || extra != EOF) ret = -1; else *bufSz = (word32)n; diff --git a/examples/tpmcertserver/tpmcertserver.c b/examples/tpmcertserver/tpmcertserver.c index 70aaa0f3..473afa33 100644 --- a/examples/tpmcertserver/tpmcertserver.c +++ b/examples/tpmcertserver/tpmcertserver.c @@ -84,11 +84,11 @@ static int TpmCsMakeKeyAndCert(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, { int rc; int devId = INVALID_DEVID; - int sigType; + int sigType = 0; TpmCryptoDevCtx tpmCtx; WOLFTPM2_KEY srk; TPMT_PUBLIC pub; - const char* subject; + const char* subject = NULL; const char* keyUsage = "serverAuth,clientAuth"; TPMA_OBJECT attr; diff --git a/src/internal.c b/src/internal.c index 97212cfc..d4ebb91a 100644 --- a/src/internal.c +++ b/src/internal.c @@ -17688,9 +17688,12 @@ int SendUserAuthRequest(WOLFSSH* ssh, byte authType, int addSig) #ifdef WOLFSSH_TPM /* When the client has a TPM key configured, prefer publickey auth so * the TPM key is used even if the server also offers password or - * keyboard-interactive. Applied before any method-specific branch. */ - if (ssh->ctx->tpmKey != NULL + * keyboard-interactive. Only strip the other methods on the first + * attempt; once publickey has been tried and rejected, allow fallback + * to password/keyboard on the next DoUserAuthFailure() retry. */ + if (ssh->ctx->tpmKey != NULL && !ssh->tpmPubkeyTried && (authType & WOLFSSH_USERAUTH_PUBLICKEY)) { + ssh->tpmPubkeyTried = 1; authType &= ~WOLFSSH_USERAUTH_PASSWORD; #ifdef WOLFSSH_KEYBOARD_INTERACTIVE authType &= ~WOLFSSH_USERAUTH_KEYBOARD; diff --git a/wolfssh/internal.h b/wolfssh/internal.h index 95c74cc9..4898d048 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -1033,6 +1033,9 @@ struct WOLFSSH { WS_UserAuthData_Keyboard kbAuth; byte kbAuthAttempts; #endif +#ifdef WOLFSSH_TPM + byte tpmPubkeyTried; /* client tried TPM publickey; allow auth fallback */ +#endif #ifdef WOLFSSH_TEST_INTERNAL word32 testSftpSendCap; /* test hook: cap per-call SFTP buffer send */ word32 testSftpStallPending; /* test hook: force N flush-only resumes */