Conversation
9c0208f to
eae465e
Compare
b186ecc to
f529484
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 61 out of 80 changed files in this pull request and generated 9 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
aidangarske
left a comment
There was a problem hiding this comment.
Skoll Code Review
Scan type: review-security
Overall recommendation: COMMENT
Findings: 19 total — 11 posted, 8 skipped
11 finding(s) posted as inline comments (see file-level comments below)
Posted findings
- [Medium] wolfTPM2_SetSessionHandle mutates session->auth.size before bounds check, leaving session inconsistent on BUFFER_E —
src/tpm2_wrap.c:1865-1872 - [Medium] wolfTPM2_SetIdentityAuth copies uninitialized stack data to handle auth on hash failure —
src/tpm2_wrap.c:9254-9255 - [Medium] XOR param encryption mask uses 1500-byte stack buffer not guarded by WOLFTPM_SMALL_STACK —
src/tpm2_param_enc.c:62-76 - [Medium] TPM2_AesCfbEncrypt/Decrypt missing WOLFSSL_AES_CFB compile guard —
src/tpm2_crypto.c:332-397 - [Medium] UART VMIN=0 allows per-byte timeout reset enabling indefinite blocking in SwTpmReceive —
src/tpm2_swtpm.c:135-158 - [Medium] UART SwTpmDisconnect leaves FD valid after SESSION_END write failure, preventing reconnection —
src/tpm2_swtpm.c:370-374 - [Medium] Auto-enable of fwtpm+swtpm on Linux x86_64 breaks builds without required wolfSSL features —
configure.ac:228-246 - [Low] tpm2_crypto.h declares crypto primitives without WOLFTPM2_NO_WOLFCRYPT guard —
wolftpm/tpm2_crypto.h:145-265 - [Low] cfsetospeed/cfsetispeed return values unchecked in UART termios configuration —
src/tpm2_swtpm.c:223-224 - [Low] distcheck auto-enables fwtpm on Linux x86_64, changing existing behavior —
Makefile.am:31 - [Info] WOLFTPM_FWTPM vs WOLFTPM_FWTPM_BUILD separation correctly implemented —
configure.ac:612-618
Skipped findings
- [Low]
getenv(TPM2_SWTPM_HOST) allows opening arbitrary character devices in UART mode - [Low]
wolfTPM2_SetAuthHandle policyAuth flag mutated before bounds check - [Low]
wolfTPM2_EncryptSecret_RSA plaintext secret not zeroized on error after generation - [Low]
TPM2_AesCfbEncrypt/Decrypt do not zeroize stack Aes object after use - [Low]
TPM2_HmacCompute does not zeroize stack Hmac object containing key material - [Low]
ByteArrayToU16/U32/U64 load helpers lack NULL pointer checks unlike store counterparts - [Info]
TPM2_ConstantCompare volatile pattern is correct and improved - [Info]
TPM2_ParamEnc_AESCFB returns mixed error code domains
Review generated by Skoll
| #ifdef DEBUG_WOLFTPM | ||
| printf("SetSessionHandle: auth size %d exceeds buffer %d\n", | ||
| session->auth.size, (int)sizeof(session->auth.buffer)); | ||
| #endif |
There was a problem hiding this comment.
🟠 [Medium] wolfTPM2_SetSessionHandle mutates session->auth.size before bounds check, leaving session inconsistent on BUFFER_E
Category: Logic
In wolfTPM2_SetSessionHandle, line 1867 assigns session->auth.size = tpmSession->handle.auth.size BEFORE the bounds check on line 1868 (if (session->auth.size > sizeof(session->auth.buffer))). If the size exceeds the buffer, the function returns BUFFER_E, but session->auth.size has already been set to the oversized value and session->sessionHandle was already mutated on line 1865. This is the exact pattern that wolfTPM2_SetAuth was explicitly fixed to avoid in the same PR (lines 1664-1669 validate bounds BEFORE mutating session state). Any subsequent code that ignores the BUFFER_E return and reads session->auth using session->auth.size as the length would read past session->auth.buffer.
session->sessionHandle = tpmSession->handle.hndl;
session->auth.size = tpmSession->handle.auth.size;
if (session->auth.size > sizeof(session->auth.buffer)) {
return BUFFER_E;
}Recommendation: Move the bounds check before assigning session->auth.size. Check tpmSession->handle.auth.size directly against sizeof(session->auth.buffer) before any session field mutations, matching the pattern used in wolfTPM2_SetAuth.
src/tpm2_param_enc.c
Outdated
| #define TPM2_XOR_MASK_MAX 1500 | ||
| #endif | ||
| } | ||
|
|
||
|
|
||
| /* Perform XOR encryption over the first parameter of a TPM packet */ | ||
| int TPM2_ParamEnc_XOR(TPM2_AUTH_SESSION *session, TPM2B_AUTH* sessKey, | ||
| TPM2B_AUTH* bindKey, TPM2B_NONCE* nonceCaller, TPM2B_NONCE* nonceTPM, | ||
| /* XOR parameter encryption/decryption (shared by client and fwTPM). | ||
| * XOR is symmetric so encrypt and decrypt are the same operation. | ||
| * nonceA/nonceB order determines direction (caller/TPM or TPM/caller). */ | ||
| int TPM2_ParamEnc_XOR( | ||
| TPMI_ALG_HASH authHash, | ||
| const BYTE *keyIn, UINT32 keyInSz, | ||
| const BYTE *nonceA, UINT32 nonceASz, | ||
| const BYTE *nonceB, UINT32 nonceBSz, | ||
| BYTE *paramData, UINT32 paramSz) | ||
| { | ||
| int rc = TPM_RC_FAILURE; | ||
| TPM2B_DATA keyIn; | ||
| TPM2B_MAX_BUFFER mask; | ||
| int rc; | ||
| BYTE mask[TPM2_XOR_MASK_MAX]; |
There was a problem hiding this comment.
🟠 [Medium] XOR param encryption mask uses 1500-byte stack buffer not guarded by WOLFTPM_SMALL_STACK
Category: Logic
The refactored TPM2_ParamEnc_XOR allocates a 1500-byte mask buffer on the stack (BYTE mask[TPM2_XOR_MASK_MAX]). The old code used TPM2B_MAX_BUFFER mask which was ~1026 bytes (2 + MAX_DIGEST_BUFFER=1024). This increases stack usage by ~474 bytes for a function in the hot path of every parameter-encrypted TPM command. The WOLFTPM_SMALL_STACK define is used extensively in the fwTPM code to heap-allocate large objects, but is not applied here. On embedded targets with limited stack (e.g., 4-8KB), this 1500-byte allocation combined with caller stack frames could cause stack overflow.
#ifndef TPM2_XOR_MASK_MAX
#define TPM2_XOR_MASK_MAX 1500
#endif
...
BYTE mask[TPM2_XOR_MASK_MAX];Recommendation: Either reduce TPM2_XOR_MASK_MAX to match old behavior (1024 bytes matches MAX_DIGEST_BUFFER), or guard the stack allocation with WOLFTPM_SMALL_STACK to heap-allocate when configured for constrained environments.
src/tpm2_crypto.c
Outdated
| #ifndef NO_AES | ||
|
|
||
| int TPM2_AesCfbEncrypt( | ||
| const byte* key, int keySz, | ||
| const byte* iv, | ||
| byte* data, word32 dataSz) | ||
| { | ||
| int rc; | ||
| Aes aes; | ||
| byte zeroIV[AES_BLOCK_SIZE]; | ||
|
|
||
| if (key == NULL || (data == NULL && dataSz > 0)) { | ||
| return BAD_FUNC_ARG; | ||
| } | ||
| if (keySz != 16 && keySz != 24 && keySz != 32) { | ||
| return BAD_FUNC_ARG; | ||
| } | ||
|
|
||
| if (iv == NULL) { | ||
| XMEMSET(zeroIV, 0, sizeof(zeroIV)); | ||
| iv = zeroIV; | ||
| } | ||
|
|
||
| rc = wc_AesInit(&aes, NULL, INVALID_DEVID); | ||
| if (rc == 0) { | ||
| rc = wc_AesSetKey(&aes, key, (word32)keySz, iv, AES_ENCRYPTION); | ||
| if (rc == 0) { | ||
| rc = wc_AesCfbEncrypt(&aes, data, data, dataSz); | ||
| } | ||
| wc_AesFree(&aes); | ||
| } | ||
| return rc; | ||
| } | ||
|
|
||
| int TPM2_AesCfbDecrypt( | ||
| const byte* key, int keySz, | ||
| const byte* iv, | ||
| byte* data, word32 dataSz) | ||
| { | ||
| int rc; | ||
| Aes aes; | ||
| byte zeroIV[AES_BLOCK_SIZE]; | ||
|
|
||
| if (key == NULL || (data == NULL && dataSz > 0)) { | ||
| return BAD_FUNC_ARG; | ||
| } | ||
| if (keySz != 16 && keySz != 24 && keySz != 32) { | ||
| return BAD_FUNC_ARG; | ||
| } | ||
|
|
||
| if (iv == NULL) { | ||
| XMEMSET(zeroIV, 0, sizeof(zeroIV)); | ||
| iv = zeroIV; | ||
| } | ||
|
|
||
| rc = wc_AesInit(&aes, NULL, INVALID_DEVID); | ||
| if (rc == 0) { | ||
| rc = wc_AesSetKey(&aes, key, (word32)keySz, iv, AES_ENCRYPTION); | ||
| if (rc == 0) { | ||
| rc = wc_AesCfbDecrypt(&aes, data, data, dataSz); | ||
| } | ||
| wc_AesFree(&aes); | ||
| } | ||
| return rc; | ||
| } | ||
|
|
There was a problem hiding this comment.
🟠 [Medium] TPM2_AesCfbEncrypt/Decrypt missing WOLFSSL_AES_CFB compile guard
Category: Logic
New functions TPM2_AesCfbEncrypt and TPM2_AesCfbDecrypt in tpm2_crypto.c are guarded only by #ifndef NO_AES but call wc_AesCfbEncrypt/wc_AesCfbDecrypt which require WOLFSSL_AES_CFB to be defined in wolfSSL. In a build configuration where AES is enabled but AES-CFB mode is not (i.e., !NO_AES but !WOLFSSL_AES_CFB), these functions will fail to compile because wc_AesCfbEncrypt/wc_AesCfbDecrypt are undeclared. The sister function TPM2_ParamEnc_AESCFB in tpm2_param_enc.c correctly uses #if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(WOLFSSL_AES_CFB). The header tpm2_crypto.h also lacks this guard at line 147.
#ifndef WOLFTPM2_NO_WOLFCRYPT
#ifndef NO_AES
int TPM2_AesCfbEncrypt(...) {
...
rc = wc_AesCfbEncrypt(&aes, data, data, dataSz); /* requires WOLFSSL_AES_CFB */Recommendation: Change the guard in tpm2_crypto.c from #ifndef NO_AES to #if !defined(NO_AES) && defined(WOLFSSL_AES_CFB), and apply the same change in tpm2_crypto.h around the function declarations.
src/tpm2_swtpm.c
Outdated
| #ifdef WOLFTPM_SWTPM_UART | ||
| /* UART: keep the port open for the next command. | ||
| * The SESSION_END tells the server the command sequence is done. | ||
| * Final cleanup of the UART FD is handled in TPM2_SwtpmCloseUART. */ | ||
| (void)ctx; |
There was a problem hiding this comment.
🟠 [Medium] UART SwTpmDisconnect leaves FD valid after SESSION_END write failure, preventing reconnection
Category: Resource Leak
In SwTpmDisconnect with UART mode, if SwTpmTransmit of TPM_SESSION_END fails, the function returns an error but leaves ctx->tcpCtx.fd unchanged. On the next TPM2_SWTPM_SendCommand call, fd >= 0 causes it to skip reconnection and reuse the broken connection. Unlike the socket path which always closes/resets FD to -1, UART has no recovery.
#ifdef WOLFTPM_SWTPM_UART
/* UART: keep the port open for the next command. */
(void)ctx;
#else
if (0 != close(ctx->tcpCtx.fd)) { ... }
ctx->tcpCtx.fd = -1;
#endifRecommendation: When SwTpmTransmit of SESSION_END fails in the UART path, close the FD and reset ctx->tcpCtx.fd to -1 to force reconnection on the next command.
configure.ac
Outdated
| # Native host defaults — auto-enable fwTPM and swTPM on Linux/BSD x86_64 / aarch64 | ||
| # so `make check` provides full coverage out of the box. Users can still | ||
| # explicitly disable with --disable-fwtpm / --disable-swtpm. | ||
| WOLFTPM_DEFAULT_FWTPM=no | ||
| WOLFTPM_DEFAULT_SWTPM=no | ||
| case $host_cpu in | ||
| x86_64|amd64|aarch64) | ||
| # Defensive exclusion: fwtpm_server uses POSIX sockets and is not | ||
| # currently portable to Windows / Darwin. Auto-enable on Linux/BSD only. | ||
| case $host_os in | ||
| *mingw*|*cygwin*|*msys*|*darwin*|*win32*) | ||
| ;; | ||
| *) | ||
| WOLFTPM_DEFAULT_FWTPM=yes | ||
| WOLFTPM_DEFAULT_SWTPM=yes | ||
| ;; | ||
| esac | ||
| ;; | ||
| esac |
There was a problem hiding this comment.
🟠 [Medium] Auto-enable of fwtpm+swtpm on Linux x86_64 breaks builds without required wolfSSL features
Category: Logic
On Linux x86_64/aarch64, configure.ac auto-enables both FWTPM and SWTPM by default. fwtpm_server requires wolfSSL with WOLFSSL_KEY_GEN, WC_RSA_NO_PADDING, HAVE_PK_CALLBACKS, and WOLFSSL_PUBLIC_MP, but configure only checks that wolfCrypt_Init exists. A user with a minimal wolfSSL install gets a silently degraded fwTPM server where key generation is ifdef'd out and RSA operations fail at runtime.
case $host_cpu in
x86_64|amd64|aarch64)
WOLFTPM_DEFAULT_FWTPM=yes
WOLFTPM_DEFAULT_SWTPM=yesRecommendation: When ENABLED_FWTPM=yes, add configure-time checks for WC_RSA_NO_PADDING and WOLFSSL_KEY_GEN. Emit AC_MSG_WARN if not found.
src/tpm2_swtpm.c
Outdated
| cfsetospeed(&tty, baud); | ||
| cfsetispeed(&tty, baud); |
There was a problem hiding this comment.
🔵 [Low] cfsetospeed/cfsetispeed return values unchecked in UART termios configuration
Category: Logic
In the UART path of SwTpmConnect, cfsetospeed() and cfsetispeed() return values are not checked. If they fail, tcsetattr() applies a partially configured termios struct, potentially causing communication at an unexpected baud rate.
cfsetospeed(&tty, baud);
cfsetispeed(&tty, baud);
// no return value checkRecommendation: Check return values of cfsetospeed and cfsetispeed. On failure, close fd and return TPM_RC_FAILURE.
| OPTION_FLAGS="$CFLAGS $CPPFLAGS $AM_CFLAGS" | ||
|
|
||
| # Add fwTPM build marker to options.h for test script detection. | ||
| # Uses WOLFTPM_FWTPM_BUILD (not WOLFTPM_FWTPM which gates server code | ||
| # in tpm2_packet.c/tpm2_param_enc.c and must only be set for the server target). | ||
| if test "x$ENABLED_FWTPM" = "xyes"; then | ||
| OPTION_FLAGS="$OPTION_FLAGS -DWOLFTPM_FWTPM_BUILD" |
There was a problem hiding this comment.
⚪ [Info] WOLFTPM_FWTPM vs WOLFTPM_FWTPM_BUILD separation correctly implemented
Category: Logic
The PR correctly separates WOLFTPM_FWTPM (per-target compile flag for server code) from WOLFTPM_FWTPM_BUILD (options.h marker for test detection). WOLFTPM_FWTPM is only set via per-target CFLAGS for fwtpm_server/fwtpm_fuzz/fwtpm_unit.test. It cannot leak into libwolftpm.la. The CMakeLists.txt mirrors this correctly.
Recommendation: No action needed. The design is sound.
src/tpm2_wrap.c
Outdated
| @@ -9370,6 +9258,9 @@ | |||
| TPM2_PrintBin(handle->auth.buffer, handle->auth.size); | |||
There was a problem hiding this comment.
🟠 [Medium] wolfTPM2_SetIdentityAuth copies uninitialized stack data to handle auth on hash failure
Category: Logic
In wolfTPM2_SetIdentityAuth, if any hash operation (wc_HashInit/Update/Final) fails, rc is non-zero but execution falls through to lines 9254-9255 which unconditionally set handle->auth.size = 16 and copy 16 bytes from the digest stack buffer into handle->auth.buffer. The digest array is a stack-local uint8_t digest[TPM_SHA256_DIGEST_SIZE] without initialization. If wc_HashFinal was never called, the digest contains whatever was on the stack. The new TPM2_ForceZero calls on lines 9261-9262 wipe the stack copies, but the garbage value has already been copied into handle->auth.buffer. The PR touches this function by adding ForceZero calls, making this in-scope.
handle->auth.size = 16;
XMEMCPY(handle->auth.buffer, digest, 16);
TPM2_ForceZero(digest, sizeof(digest));
TPM2_ForceZero(serialNum, sizeof(serialNum));Recommendation: Guard lines 9254-9255 with if (rc == 0) so the handle auth is only set when hash operations succeeded. On failure, set handle->auth.size = 0.
Note: Referenced line (
src/tpm2_wrap.c:9254-9255) is outside the diff hunk. Comment anchored to nearest changed region.
| #endif | ||
|
|
||
| return rc; | ||
| } |
There was a problem hiding this comment.
🟠 [Medium] UART VMIN=0 allows per-byte timeout reset enabling indefinite blocking in SwTpmReceive
Category: Logic
With VMIN=0 and VTIME=200 (20 seconds), each read() call starts its own independent 20-second timer. SwTpmReceive loops calling read() until all bytes_remaining are received. A malicious or malfunctioning UART device can send one byte every ~19 seconds, resetting the timer each time. For a 4096-byte response, this extends the effective timeout to ~22 hours instead of 20 seconds.
tty.c_cc[VMIN] = 0;
tty.c_cc[VTIME] = 200; /* 20 second timeout */
// SwTpmReceive loops: while (bytes_remaining > 0) { wrc = read(...); ... }Recommendation: Track wall-clock time across the entire SwTpmReceive loop using clock_gettime(CLOCK_MONOTONIC) and abort if total elapsed time exceeds a maximum threshold.
Note: Referenced line (
src/tpm2_swtpm.c:135-158) is outside the diff hunk. Comment anchored to nearest changed region.
| @@ -47,6 +47,7 @@ include docs/include.am | |||
| include wrapper/include.am | |||
There was a problem hiding this comment.
🔵 [Low] distcheck auto-enables fwtpm on Linux x86_64, changing existing behavior
Category: Logic
AM_DISTCHECK_CONFIGURE_FLAGS does not pass --disable-fwtpm. On Linux x86_64, the auto-enable logic will enable fwtpm during distcheck, changing existing distcheck behavior and potentially failing if wolfSSL lacks required features.
AM_DISTCHECK_CONFIGURE_FLAGS = --enable-swtpm @DISTCHECK_SWTPM_PORT_FLAG@Recommendation: Add --disable-fwtpm to AM_DISTCHECK_CONFIGURE_FLAGS, or document the changed behavior.
Note: Referenced line (
Makefile.am:31) is outside the diff hunk. Comment anchored to nearest changed region.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 52 out of 68 changed files in this pull request and generated 7 comments.
Comments suppressed due to low confidence (1)
CMakeLists.txt:727
- Installing/exporting the
wolftpm_wolfssl_depINTERFACE target is likely unintended and can complicate downstreamfind_package(wolftpm)usage (it also doesn’t represent an installable artifact). Prefer exporting onlywolftpm(and any real binaries likefwtpm_server) and model the wolfSSL dependency via usage requirements onwolftpm(or by generating a config that finds wolfSSL). If you keep an INTERFACE helper, consider avoidinginstall(TARGETS ...)for it.
if(BUILD_WOLFTPM_LIB)
install(TARGETS wolftpm wolftpm_wolfssl_dep
EXPORT wolftpm-targets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| case FWTPM_TIS_DATA_FIFO: | ||
| case FWTPM_TIS_XDATA_FIFO: { | ||
| /* Read response data from FIFO */ | ||
| UINT32 i; | ||
| UINT32 avail; | ||
| /* Snapshot read state to locals for TOCTOU safety */ | ||
| UINT32 rpos = regs->fifo_read_pos; | ||
| UINT32 rlen = regs->rsp_len; | ||
| if (rpos > rlen || rpos >= sizeof(regs->rsp_buf)) { | ||
| avail = 0; | ||
| } | ||
| else { | ||
| avail = rlen - rpos; | ||
| } | ||
| if (len > avail) { | ||
| len = avail; | ||
| } | ||
| if (len > sizeof(regs->reg_data)) { | ||
| len = (UINT32)sizeof(regs->reg_data); | ||
| } | ||
| for (i = 0; i < len; i++) { | ||
| regs->reg_data[i] = regs->rsp_buf[rpos++]; | ||
| } | ||
| regs->fifo_read_pos = rpos; | ||
| /* Update data availability */ | ||
| if (rpos >= rlen) { | ||
| /* All response bytes read */ | ||
| regs->sts = TisBuildSts( | ||
| FWTPM_STS_VALID | FWTPM_STS_COMMAND_READY, | ||
| FWTPM_TIS_BURST_COUNT); | ||
| } | ||
| /* Return early - data already in reg_data */ | ||
| return; | ||
| } |
There was a problem hiding this comment.
The server clamps len (and may return early in FIFO reads) but it does not clear the full regs->reg_data buffer. Since the client side copies the originally requested size bytes, a read request larger than len can leak stale bytes left in shared memory from prior operations. Fix by zeroing regs->reg_data for its full size on every read path before writing the response bytes (and/or by writing back the effective length and having the client copy only that length).
src/fwtpm/fwtpm_tis_shm.c
Outdated
| int openFlags = O_CREAT | O_RDWR | O_TRUNC | O_NOFOLLOW; | ||
|
|
||
| #ifdef O_CLOEXEC | ||
| openFlags |= O_CLOEXEC; | ||
| #endif | ||
|
|
||
| /* Create shared memory file */ | ||
| fd = open(FWTPM_TIS_SHM_PATH, openFlags, 0600); |
There was a problem hiding this comment.
O_NOFOLLOW is used unconditionally, but it is not available on all POSIX targets/stdlib combinations. This can cause build failures on platforms where the macro is missing. Guard O_NOFOLLOW with #ifdef O_NOFOLLOW (or add a local fallback #ifndef O_NOFOLLOW #define O_NOFOLLOW 0 #endif, consistent with the UART transport code) to keep compilation portable.
hal/tpm_io_fwtpm.c
Outdated
| client->shmFd = -1; | ||
|
|
||
| /* Open existing shared memory file */ | ||
| fd = open(FWTPM_TIS_SHM_PATH, O_RDWR | O_NOFOLLOW | O_CLOEXEC); |
There was a problem hiding this comment.
O_CLOEXEC is not guaranteed to be defined on all supported platforms/toolchains. Since this file is compiled as part of the client library (not just fwTPM), an unconditional O_CLOEXEC can break builds. Use an #ifdef O_CLOEXEC guarded flag (and, if needed, fall back to setting FD_CLOEXEC via fcntl) to preserve portability.
| ptr = (const char*)buffer; | ||
| remaining = bufSz; | ||
| while (remaining > 0) { | ||
| wrc = write(ctx->tcpCtx.fd, ptr, remaining); | ||
| if (wrc <= 0) { | ||
| #ifdef WOLFTPM_DEBUG_VERBOSE | ||
| printf("Failed to send the TPM command to fd %d, got errno %d =" | ||
| "%s\n", ctx->tcpCtx.fd, errno, strerror(errno)); | ||
| #endif | ||
| rc = TPM_RC_FAILURE; | ||
| break; | ||
| } | ||
| remaining -= wrc; | ||
| ptr += wrc; | ||
| } |
There was a problem hiding this comment.
In the new transmit loop, write() failures due to EINTR (and potentially EAGAIN depending on FD settings) are treated as hard errors. This can make UART/socket communication flaky under signal delivery or non-blocking configurations. Consider retrying on EINTR, and handling EAGAIN/EWOULDBLOCK with a bounded wait (poll/select) if those modes are possible for this transport.
| endif() | ||
|
|
||
| # wolfSSL/wolfCrypt dependency (shared between wolftpm library and fwtpm targets) | ||
| add_library(wolftpm_wolfssl_dep INTERFACE) |
There was a problem hiding this comment.
Installing/exporting the wolftpm_wolfssl_dep INTERFACE target is likely unintended and can complicate downstream find_package(wolftpm) usage (it also doesn’t represent an installable artifact). Prefer exporting only wolftpm (and any real binaries like fwtpm_server) and model the wolfSSL dependency via usage requirements on wolftpm (or by generating a config that finds wolfSSL). If you keep an INTERFACE helper, consider avoiding install(TARGETS ...) for it.
| NAMESPACE wolfssl::) | ||
| endif() |
There was a problem hiding this comment.
Installing/exporting the wolftpm_wolfssl_dep INTERFACE target is likely unintended and can complicate downstream find_package(wolftpm) usage (it also doesn’t represent an installable artifact). Prefer exporting only wolftpm (and any real binaries like fwtpm_server) and model the wolfSSL dependency via usage requirements on wolftpm (or by generating a config that finds wolfSSL). If you keep an INTERFACE helper, consider avoiding install(TARGETS ...) for it.
configure.ac
Outdated
| # Native host defaults — auto-enable fwTPM and swTPM on Linux/BSD x86_64 / aarch64 | ||
| # so `make check` provides full coverage out of the box. Users can still | ||
| # explicitly disable with --disable-fwtpm / --disable-swtpm. | ||
| WOLFTPM_DEFAULT_FWTPM=no | ||
| WOLFTPM_DEFAULT_SWTPM=no | ||
| case $host_cpu in | ||
| x86_64|amd64|aarch64) | ||
| # Defensive exclusion: fwtpm_server uses POSIX sockets and is not | ||
| # currently portable to Windows / Darwin. Auto-enable on Linux/BSD only. | ||
| case $host_os in | ||
| *mingw*|*cygwin*|*msys*|*darwin*|*win32*) | ||
| ;; | ||
| *) | ||
| WOLFTPM_DEFAULT_FWTPM=yes | ||
| WOLFTPM_DEFAULT_SWTPM=yes | ||
| ;; | ||
| esac | ||
| ;; | ||
| esac |
There was a problem hiding this comment.
This changes the default configure behavior on common Linux/BSD hosts to auto-enable both --enable-fwtpm and --enable-swtpm. The PR description focuses on adding fwTPM, but doesn’t call out this default-behavior change, which can affect existing users/builds (e.g., new optional dependency expectations and different make check behavior). Consider explicitly documenting this change in the PR description and/or project docs (or defaulting to disabled and enabling only in CI/scripts).
…1 support. Copilot peer review fixes.
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)