Add secure file I/O utilities, memory wiping, and tests - #278
Conversation
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #278
Scan targets checked: wolfclu-bugs, wolfclu-src
No new issues found in the changed files. ✅
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #278
Scan targets checked: wolfclu-bugs, wolfclu-src
Findings: 9
9 finding(s) posted as inline comments (see file-level comments below)
This review was generated automatically by Fenrir. Findings are non-blocking.
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #278
Scan targets checked: wolfclu-bugs, wolfclu-src
Findings: 6
5 finding(s) posted as inline comments (see file-level comments below)
Critical (1)
Unbalanced #endif in clu_sign.c breaks every build
File: src/sign-verify/clu_sign.c:1244
Function: file scope
Category: Incorrect macro expansion
The PR deleted the file's opening #ifndef WOLFCLU_NO_FILESYSTEM (replacing it with the WOLFCLU_MAX_FILE_SIZE define) but left the closing #endif at line 1244. WOLFCLU_NO_FILESYSTEM appears nowhere else in the file, and the 18 #if* directives are matched by 19 #endifs, so the preprocessor errors with "#endif without #if" in all configurations.
Recommendation: Restore #ifndef WOLFCLU_NO_FILESYSTEM after the WOLFCLU_MAX_FILE_SIZE define so it pairs with the trailing #endif.
Referenced code: src/sign-verify/clu_sign.c:1244-1247 (4 lines)
This review was generated automatically by Fenrir. Findings are non-blocking.
| finalOutFNm = NULL; | ||
| } | ||
| if (derBuf != NULL) { | ||
| wolfCLU_ForceZero(derBuf, derSz); |
There was a problem hiding this comment.
🔴 [High] Negative derSz passed to wolfCLU_ForceZero in ED25519 keygen cleanup · Incorrect sizeof/type usage
derSz holds the signed return of wc_Ed25519PrivateKeyToDer/wc_Ed25519PublicKeyToDer (lines 169-172, 274-279); on a negative return the switch breaks with derBuf still allocated, and the new cleanup converts that negative int to unsigned int len, making wc_ForceZero write ~4 GiB past the buffer. The sibling RSA cleanup guards with derBufSz > 0. Adjacent to known finding #1116, which is the inverse (zeroing absent) and would not be fixed by this guard.
Related known finding #1116 (similar but distinct): Both affect ED25519 cleanup buffers in wolfCLU_genKey_ED25519. #1116 is missing zeroization before free, while this finding is an unsafe zeroization length after a negative DER-conversion result; fixing #1116 requires adding wipes, whereas this requires positive-size guards.
Fix: Guard both cleanup wipes with derSz > 0 / pemSz > 0, matching wolfCLU_genKey_RSA.
| runFixture("testKeyFileRefusalsWin", testKeyFileRefusalsWin); | ||
| runFixture("testOpenExistingSecureFileWin", testOpenExistingSecureFileWin); | ||
| #endif | ||
| runFixture("testSecureFileBios", testSecureFileBios); |
There was a problem hiding this comment.
🔵 [Low] New secure-file helpers with documented error paths have no unit coverage · Missing edge-case coverage on a function the PR also changed
The suite exercises the read/open/BIO/DER helpers but never calls wolfCLU_CloseOutFile (NULL no-op and OUTPUT_FILE_ERROR flush path), wolfCLU_RejectSamePath (SAME vs UNDETERMINED), wolfCLU_OpenPairedOutFile, wolfCLU_OpenSecureFileForUpdate (ENOENT create-fallback used by the XMSS write callback), or wolfCLU_LogKeyOpenFailure — all added by this PR.
Fix: Add fixtures for wolfCLU_CloseOutFile(NULL, ...), wolfCLU_RejectSamePath on both non-distinct results, and wolfCLU_OpenSecureFileForUpdate on missing/existing/symlink paths.
| finalOutFNm = NULL; | ||
| } | ||
| if (derBuf != NULL) { | ||
| wolfCLU_ForceZero(derBuf, derSz); |
There was a problem hiding this comment.
🟠 [Medium] Negative derSz passed as unsigned length to wolfCLU_ForceZero in ED25519 keygen cleanup · Buffer overflows
The new cleanup wipe passes derSz directly to wolfCLU_ForceZero()'s unsigned int length. When wc_Ed25519PrivateKeyToDer() (line 169) or wc_Ed25519PublicKeyToDer() (line 275) fails on its second, encoding call, derSz holds a negative error code while derBuf is allocated, so the wipe writes ~4 GB past the allocation. Adjacent to known finding #38, which is the inverse defect (wipe absent entirely).
Related known finding #1116 (similar but distinct): Both affect ED25519 DER cleanup in wolfCLU_genKey_ED25519, but #1116 omits zeroization before free, whereas this finding invokes zeroization with a negative size converted to unsigned. The root causes and required patches differ.
Fix: Guard with if (derSz > 0) before the wipe, matching the derBufSz > 0 guard already used in wolfCLU_genKey_RSA().
|
|
||
| case WOLFCLU_OUTFILE: | ||
| bioOut = wolfSSL_BIO_new_file(optarg, "wb"); | ||
| bioOut = wolfCLU_OpenOutFileBio(optarg); |
There was a problem hiding this comment.
🔵 [Low] base64 command left without the new -in/-out same-file guard · File handling vulnerabilities
This call site was switched to the new helper but is still a truncating open performed during option parsing, with no wolfCLU_RejectSamePath() check like the one the PR added to enc, dgst, hash, pkcs7, pkcs8, pkey and rsa. base64 -in f -out f therefore truncates f before it is read, and the command silently succeeds on empty input.
Fix: Defer the -out open until after -in has been read and gate it on wolfCLU_RejectSamePath(inPath, outPath).
| runFixture("testOpenExistingSecureFileWin", testOpenExistingSecureFileWin); | ||
| #endif | ||
| runFixture("testSecureFileBios", testSecureFileBios); | ||
| runFixture("testDerSetLength", testDerSetLength); |
There was a problem hiding this comment.
🔵 [Low] New secure-file helpers with security-relevant refusal paths have no unit coverage · Missing edge-case coverage on a function the PR also changed
The suite covers wolfCLU_ReadFileToBuffer, wolfCLU_PathsRefEqual, wolfCLU_CreateSecureFile, wolfCLU_OpenExistingSecureFile, wolfCLU_OpenOutFileDistinctFrom and the BIO wrappers, but never exercises wolfCLU_OpenSecureFileForUpdate() (the XMSS private-key rewrite path and its ENOENT-only create fallback), wolfCLU_RejectSamePath(), wolfCLU_OpenPairedOutFile(), or wolfCLU_CloseOutFile()'s failure branch.
Fix: Add fixtures asserting the create/no-truncate/refusal behavior of wolfCLU_OpenSecureFileForUpdate() and the SAME/UNDETERMINED refusals of wolfCLU_RejectSamePath() and wolfCLU_OpenPairedOutFile().
Added helper functions to remove races in file ops, and refactored sites to call helper functions, and added test coverage. Also fixed CI for no_filesystem builds.