Conversation
9c0208f to
eae465e
Compare
b186ecc to
f529484
Compare
…1 support. Copilot peer review fixes.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 53 out of 69 changed files in this pull request and generated 9 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #474
Scan targets checked: wolftpm-bugs, wolftpm-consttime, wolftpm-defaults, wolftpm-mutation, wolftpm-proptest, wolftpm-src, wolftpm-zeroize
Findings: 4
4 finding(s) posted as inline comments (see file-level comments below)
This review was generated automatically by Fenrir. Findings are non-blocking.
…env-var override risk
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 53 out of 71 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
src/tpm2_swtpm.c:199
- For UART mode,
read()can legally return 0 due toVMIN=0/VTIME>0timeout (not EOF). Treatingwrc==0as EOF will break long-running fwTPM operations over UART (e.g., RSA keygen) and prevents the cumulative timeout logic below from ever triggering. Fix by handlingwrc==0differently underWOLFTPM_SWTPM_UART(e.g., continue polling until the cumulative timeout elapses), while keeping the EOF behavior for sockets.
while (bytes_remaining > 0) {
wrc = read(ctx->tcpCtx.fd, ptr, bytes_remaining);
if (wrc < 0) {
/* Retry on EINTR; treat EAGAIN/EWOULDBLOCK as transient too. */
if (errno == EINTR
#ifdef EAGAIN
|| errno == EAGAIN
#endif
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || EWOULDBLOCK != EAGAIN)
|| errno == EWOULDBLOCK
#endif
) {
continue;
}
#ifdef DEBUG_WOLFTPM
printf("Failed to read from TPM socket %d, got errno %d"
" = %s\n", ctx->tcpCtx.fd, errno, strerror(errno));
#endif
rc = TPM_RC_FAILURE;
break;
}
if (wrc == 0) {
#ifdef DEBUG_WOLFTPM
printf("Failed to read from TPM socket: EOF\n");
#endif
rc = TPM_RC_FAILURE;
break;
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…e issue. Fix minor ticket issue after new tests.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 53 out of 71 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (1)
src/tpm2_swtpm.c:199
- In UART mode, termios is configured with
VMIN=0andVTIME>0, whereread()returning 0 indicates a timeout (no bytes yet), not EOF. Treatingwrc==0as EOF will cause spurious failures for long-running TPM operations. ForWOLFTPM_SWTPM_UART, handlewrc==0as a transient timeout and continue waiting until the cumulative timeout is reached (theCLOCK_MONOTONICblock you added is a good place to enforce the overall limit). Keep the EOF behavior for socket mode.
if (wrc == 0) {
#ifdef DEBUG_WOLFTPM
printf("Failed to read from TPM socket: EOF\n");
#endif
rc = TPM_RC_FAILURE;
break;
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| session->auth.size = authDigestSz + handle->auth.size; | ||
| XMEMCPY(&session->auth.buffer[authDigestSz], handle->auth.buffer, | ||
| handle->auth.size); | ||
| if (handle->name.size > sizeof(session->name.name)) { | ||
| return BUFFER_E; | ||
| } | ||
| session->name.size = handle->name.size; | ||
| if (session->name.size > sizeof(session->name.name)) { | ||
| session->name.size = sizeof(session->name.name); /* truncate */ | ||
| } | ||
| XMEMCPY(session->name.name, handle->name.name, session->name.size); | ||
| return TPM_RC_SUCCESS; |
There was a problem hiding this comment.
Truncating handle->name.size here can leave the session in a state where session->name no longer matches the real object name. That can break authorization/HMAC computations in later command flows and can also hide an upstream size/encoding error. Prefer keeping the previous behavior: validate handle->name.size against sizeof(session->name.name) and return BUFFER_E rather than truncating.
| /* Clamp len for scalar registers (max 4 bytes) and zero-fill | ||
| * to prevent stale data in reg_data from being read back */ | ||
| if (len > 4) { | ||
| len = 4; | ||
| } | ||
| XMEMSET(regs->reg_data, 0, len); | ||
| /* Pack value into reg_data (little-endian, matching TIS spec) */ | ||
| if (len >= 1) regs->reg_data[0] = (BYTE)(val); | ||
| if (len >= 2) regs->reg_data[1] = (BYTE)(val >> 8); | ||
| if (len >= 3) regs->reg_data[2] = (BYTE)(val >> 16); | ||
| if (len >= 4) regs->reg_data[3] = (BYTE)(val >> 24); |
There was a problem hiding this comment.
This read path only zeroes len bytes (clamped to 4), but the client-side HAL copies the originally requested size bytes from reg_data and does not know about the server-side clamp. That can leak stale shared-memory contents beyond the first 4 bytes. To prevent data disclosure, zero the entire regs->reg_data buffer (or at least regs->reg_len bytes as requested) before writing the scalar register bytes.
| # Show UART output (filter emulator noise) | ||
| echo "" | ||
| echo "--- fwTPM output ---" | ||
| grep -E "^===|^fwTPM|^ |^Running|^ Startup|^ SelfTest|^ GetRandom|^ GetCapability|^ Random|^All self|^SELF-TEST" "$LOG" |
There was a problem hiding this comment.
This script runs with set -e, so if the grep pattern matches nothing (e.g., on early boot failure or different output), grep exits 1 and the whole script aborts before the intended result checks and log tail. Consider appending || true (or temporarily disabling set -e around this grep) so the script can still report failures and show diagnostics consistently.
| grep -E "^===|^fwTPM|^ |^Running|^ Startup|^ SelfTest|^ GetRandom|^ GetCapability|^ Random|^All self|^SELF-TEST" "$LOG" | |
| grep -E "^===|^fwTPM|^ |^Running|^ Startup|^ SelfTest|^ GetRandom|^ GetCapability|^ Random|^All self|^SELF-TEST" "$LOG" || true |
| } | ||
| #ifndef O_CLOEXEC | ||
| /* Fallback for platforms without O_CLOEXEC */ | ||
| (void)fcntl(fd, F_SETFD, FD_CLOEXEC); |
There was a problem hiding this comment.
fcntl(fd, F_SETFD, FD_CLOEXEC) overwrites existing FD flags instead of preserving them. Use F_GETFD and OR-in FD_CLOEXEC (as done elsewhere in the PR) so you don't accidentally clear other descriptor flags.
| (void)fcntl(fd, F_SETFD, FD_CLOEXEC); | |
| { | |
| int fdFlags = fcntl(fd, F_GETFD); | |
| if (fdFlags >= 0) { | |
| (void)fcntl(fd, F_SETFD, fdFlags | FD_CLOEXEC); | |
| } | |
| } |
Summary
TPM2_Packet_ParseU16Bufvariant for safer response parsingfwTPM Server
Core TPM 2.0 command processing in
src/fwtpm/:fwtpm_command.c— 105 command handlers with full auth, sessions, parameter encryptionfwtpm_nv.c— TLV journal NV storage (file-based default, HAL-abstracted for flash)fwtpm_io.c— Socket transport (mssim + swtpm protocol auto-detection)fwtpm_tis.c/fwtpm_tis_shm.c— TIS register interface via POSIX shared memoryfwtpm_crypto.c— Key generation, sign/verify, seed encrypt/decrypt helpersBuild:
./configure --enable-fwtpm && makeExample: wolfSSL/wolftpm-examples#1
Primary Key Derivation (TPM 2.0 Part 1 Section 26)
UART Transport (
--enable-swtpm=uart)New transport option for wolfTPM client library to communicate with embedded fwTPM over serial:
./configure --enable-swtpm=uart— uses termios serial I/O instead of TCP socketsTPM2_SWTPM_HOSTenv var selects serial device at runtimeTesting
scripts/tpm2_tools_test.sh)examples/run_examples.sh)tests/fuzz/)scripts/fwtpm_emu_test.sh)