You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Authenticated `EED4` file format with header-bound associated data
28
28
29
-
No temp files, only in-memory buffer until explicitly written
29
+
Atomic encrypted saves with same-directory temp files (ciphertext only)
30
30
31
-
Compatible with OpenSSL 3.x API → uses EVP_MAC, no deprecated HMAC_CTX
31
+
Compatible with OpenSSL 3.5+ API → uses `EVP_KDF` for Argon2id and `EVP_CIPHER` AEAD APIs
32
+
33
+
Encrypted recovery snapshots after each mutating command and mirrored backup copies for the latest durable state
32
34
33
35
Simple ed-like commands:
34
36
@@ -49,18 +51,64 @@ Simple ed-like commands:
49
51
50
52
Security Notes
51
53
52
-
Editor uses AES-256-CBC with random IV per file
54
+
Editor uses AES-256-GCM with a random 96-bit nonce per file
55
+
56
+
Uses an authenticated `EED4` header and currently accepts only the fixed supported Argon2id profile
57
+
58
+
Authenticates the full header as AEAD associated data before any plaintext is accepted
59
+
60
+
If AEAD authentication fails, the file is not opened
53
61
54
-
Uses PBKDF2 with 100,000 iterations (easy to increase or switch to Argon2)
62
+
Saves are atomic: encrypted output is written to a temp file, synced, then renamed over the target
55
63
56
-
Adds HMAC-SHA-256 over IV + ciphertext → integrity check
64
+
Each open file is held with an exclusive advisory lock, and saves refuse to proceed if the pathname no longer points at the file originally opened
57
65
58
-
If MAC verification fails, the file is not opened
66
+
The editor save path intentionally writes only ciphertext; swap, hibernation, snapshots, and backups remain outside the editor's control
59
67
60
-
No plaintext is written to disk unless you explicitly write
68
+
Every mutating command refreshes an encrypted `.recovery` snapshot, and each save refreshes an encrypted `.bak` mirror before the primary rename so crashes still leave a recoverable ciphertext copy
69
+
70
+
Quit will attempt to refresh a final encrypted recovery snapshot before exiting if the in-memory buffer is dirty and the prior recovery snapshot is stale
71
+
72
+
The parent directory must be owned by the current user and not writable by group or others
61
73
62
74
Plaintext buffer and password are securely wiped on exit
63
75
76
+
Memory locking is attempted at startup; set `EED_REQUIRE_MLOCK=1` to fail closed on hosts where `mlockall()` is unavailable
77
+
78
+
Current release writes an `EED4` file format and does not open files written by older releases
79
+
80
+
81
+
Verification
82
+
83
+
`make` builds the release binary
84
+
85
+
`make asan` builds the sanitizer-enabled regression binary
The editor remains a C codebase by design. The current hardening strategy is therefore to narrow the dangerous surface, freeze the crypto container, and keep verification pressure high rather than to promise language-level memory safety.
6
+
7
+
## Immediate Controls
8
+
9
+
- Keep the crypto format fixed and documented in `docs/file-format-eed4.md`.
10
+
- Keep `make verify` mandatory before release.
11
+
- Keep `make fuzz-run` in regular use against `load_encrypted()`.
12
+
- Preserve explicit cleansing of passwords, keys, tags, and plaintext buffers.
13
+
- Keep risky helper functions `static` and continue preferring fixed-size buffers and explicit bounds checks.
14
+
15
+
## Near-Term Assurance Work
16
+
17
+
- Add stricter warning gates such as `-Wconversion`, `-Wshadow`, and `-Wstrict-prototypes` once the tree is clean under them.
18
+
- Run `clang-tidy` and `cppcheck` in CI as advisory jobs.
19
+
- Perform a manual MISRA-C-oriented review of the parser and save path, while being explicit that the project is not yet claiming formal MISRA compliance.
20
+
- Expand deterministic test vectors to cover empty files and maximum-length line edge cases.
21
+
22
+
## Higher-Assurance Options Without Leaving C
23
+
24
+
- Split the file-format parser and serializer into a smaller translation unit with a narrower API.
25
+
- Add CBMC or Frama-C proofs for header parsing, bounds checks, and line-count safety properties.
26
+
- Add negative tests for every rejected header field combination in `EED4`.
27
+
- Consider a dedicated hardened build profile with stack canaries, full RELRO, and platform-specific linker hardening flags.
28
+
29
+
## Explicit Non-Claim
30
+
31
+
This roadmap improves assurance inside a C codebase. It does not make C memory-safe, and it should not be described that way.
- Header authentication: the full 48-byte header is passed as AEAD associated data
14
+
15
+
## Plaintext Encoding
16
+
17
+
The editor serializes the in-memory buffer as a byte stream of newline-terminated lines. Each stored line is emitted exactly as typed, followed by `0x0a`. An empty editor buffer produces an empty plaintext stream.
This repository can now produce a repeatable internal verification bundle, but an actual independent audit still requires a separate reviewer and a signing key that are not part of this workspace.
6
+
7
+
## Minimum Release Procedure
8
+
9
+
1. Build from a clean checkout of the exact commit being released.
10
+
2. Set a fixed `SOURCE_DATE_EPOCH` for the release run.
11
+
3. Run `make clean all verify audit-manifest`.
12
+
4. Archive the resulting binary plus `dist/sha256.txt` and `dist/build-info.txt`.
13
+
5. Record the exact OpenSSL version, compiler version, operating system, and committed `EED4` format spec in the release notes.
14
+
15
+
## External Audit Procedure
16
+
17
+
1. Hand the auditor the exact commit ID, the release artifact, and the audit manifest.
18
+
2. Require the auditor to rebuild from the same commit and compare the resulting hashes against `dist/sha256.txt`.
19
+
3. Scope the audit to the exact binary hash being shipped, not just to the source tree in general.
20
+
4. Treat any source change, compiler change, or dependency change as a new audit candidate.
21
+
22
+
## Signed Release Procedure
23
+
24
+
1. Generate the audit manifest with `make audit-manifest`.
25
+
2. Sign `dist/sha256.txt` and the release notes with an offline key that is kept outside the build machine.
26
+
3. Publish the signature, the public verification key, and the binary hash together.
27
+
4. Make signature verification part of the deployment checklist.
28
+
29
+
The repository does not ship a signing key, and it should not. Signed releases need an operator-controlled trust root.
30
+
31
+
## Reproducibility Notes
32
+
33
+
- Avoid embedding ad hoc local changes, generated files, or untracked patches in the release build.
34
+
- Pin the compiler family and OpenSSL build used for production.
35
+
- Rebuild from scratch for each release instead of reusing a previously compiled binary.
36
+
- Keep the deterministic vector in `docs/file-format-eed4.md` and `tests/test_vectors.py` in sync with the shipping format.
0 commit comments