Skip to content

proto_crypt: clear the remaining stack buffers - #437

Open
woahwhattheheck wants to merge 2 commits into
Tarsnap:masterfrom
woahwhattheheck:proto-crypt-clear-stack
Open

woahwhattheheck wants to merge 2 commits into
Tarsnap:masterfrom
woahwhattheheck:proto-crypt-clear-stack

Conversation

@woahwhattheheck

@woahwhattheheck woahwhattheheck commented Sep 6, 2026 •

Copy link
Copy Markdown

Fixes #436.

#426 wiped dk_2 and nonce_y in proto_crypt_mkkeys(). Two buffers holding
key material in the same file were not covered by it:

  • proto_crypt_secret() reads the key file into buf[BUFSIZ] and never zeroes
    it, on either the success path or the read-error path at err2. That buffer
    is the pre-image of the shared secret — the whole key file, for a key file of
    BUFSIZ bytes or less. The function already wipes the SHA-256 context two
    lines above, and proto_crypt_secret_free() zeroes the derived secret; the
    buffer it was derived from was the gap. Both spiped and spipe call this
    once at startup and then run for the lifetime of the process.
  • proto_crypt_dhmac() leaves dk_1, the derived diffie-hellman MAC keys, in
    the frame when it returns. Called once per connection.

Three insecure_memzero() calls, using the idiom from #426.

Deliberately not covered

  • ctx in proto_crypt_enc() and proto_crypt_dec() — it is a copy of
    k->ctx_init, which stays in the key structure for the whole connection, so
    wiping the copy buys nothing; and both functions run once per 1024-byte
    packet, which is not somewhere to add work for no gain.
  • nonce_CS in proto_crypt_dhmac() — the nonces are sent over the wire in
    the clear.

Happy to add either if you would rather have the file uniformly wiped.

Testing

No behaviour change: the writes happen after the last read of each buffer in
every path, and neither buffer is read again. insecure_memzero.h is already
included by this file.

426 wiped dk_2 and nonce_y in proto_crypt_mkkeys().  Two buffers holding
key material in the same file were not covered by it.

proto_crypt_secret() reads the key file into buf[BUFSIZ] and never zeroes
it, on the success path or on the read-error path at err2.  That buffer
holds the pre-image of the shared secret, and for a key file of BUFSIZ
bytes or less it holds all of it.  The function already wipes the SHA-256
context two lines above, and proto_crypt_secret_free() zeroes the derived
secret; the buffer it was derived from was the gap.  Both spiped and
spipe call this once at startup and then run for the lifetime of the
process.

proto_crypt_dhmac() leaves dk_1, the derived diffie-hellman MAC keys, in
the frame when it returns.

ctx in proto_crypt_enc() and proto_crypt_dec() is left alone: it is a
copy of k->ctx_init, which stays in the key structure for the whole
connection, and those run once per packet.  nonce_CS is left alone
because the nonces go over the wire in the clear.
Preserve the existing proto_crypt.c secret-buffer wipes while rejoining Tarsnap/spiped master at 1881fdb. Upstream drift is disjoint from lib/proto/proto_crypt.c.
@tokenjunkielabs

Copy link
Copy Markdown

Following up on first-reporter bug bounty #436. This PR is the woahwhattheheck carrier for the unwiped key-file and DHMAC stack buffers. Please review the report/fix when convenient and classify #436 under the repository's published bug-bounty schedule, including the applicable payment route if it qualifies. I am not presuming a tier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

[bug bounty] Key file contents and dhmac keys are left on the stack in proto_crypt.c

2 participants