Skip to content

Use constant-time comparison for rpcapd password hash verification#1660

Open
kodareef5 wants to merge 1 commit intothe-tcpdump-group:masterfrom
kodareef5:fix-rpcapd-password-timing
Open

Use constant-time comparison for rpcapd password hash verification#1660
kodareef5 wants to merge 1 commit intothe-tcpdump-group:masterfrom
kodareef5:fix-rpcapd-password-timing

Conversation

@kodareef5
Copy link
Copy Markdown

rpcapd/daemon.c line 1554 compares crypt() password hashes using strcmp(), which returns early on the first character mismatch. Replace with a constant-time XOR accumulation loop that examines all characters regardless of match position.

While crypt() dominates the overall timing, using constant-time comparison for authentication credentials is defense-in-depth best practice.

rpcapd/daemon.c:1554 compares crypt() password hashes using
strcmp(), which returns early on the first character mismatch.
Replace with a constant-time XOR accumulation loop.

While the crypt() call dominates the overall timing, using
constant-time comparison for authentication credentials is
defense-in-depth best practice.
@infrastation
Copy link
Copy Markdown
Member

Speaking of existing solutions to this problem, memcmp(3) refers to consttime_memequal(3), which is even shorter. More generally, it would be nice to find a way not to have to solve such problems in the first place, similarly to how git can work over SSH, but implements neither SSH nor the involved authentication.

@kodareef5
Copy link
Copy Markdown
Author

Good point about consttime_memequal(3) — it's a cleaner solution where available. The challenge is portability: it's a NetBSD/OpenBSD extension, not present on Linux or macOS. We could add a configure check and fall back to the manual implementation, or use the manual version unconditionally for simplicity. Happy to go either way.

On the broader question — I agree that delegating auth to SSH is the better long-term model. But as long as rpcapd's password authentication path exists and is usable, the hash comparison in that path should be constant-time. Even if most users are on SSH, the code is still compiled and callable.

snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
return -1;
/*
* Use constant-time comparison to prevent timing
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be precise, the comparison is constant-time in the "the time is padded so that shorter strings take the same time as longer strings", but the strlen() calls are O(N).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"...and the comparison doesn't stop as soon as it knows that the strings aren't equal".

@guyharris
Copy link
Copy Markdown
Member

Good point about consttime_memequal(3) — it's a cleaner solution where available. The challenge is portability: it's a NetBSD/OpenBSD extension, not present on Linux or macOS. We could add a configure check and fall back to the manual implementation, or use the manual version unconditionally for simplicity. Happy to go either way.

We could just take the NetBSD code and add it as rpcap/missing/consttime_memequal.c, and use that if the OS doesn't have it.

On the broader question — I agree that delegating auth to SSH is the better long-term model. But as long as rpcapd's password authentication path exists and is usable, the hash comparison in that path should be constant-time. Even if most users are on SSH, the code is still compiled and callable.

Yes, this is probably the right thing for now.

@guyharris
Copy link
Copy Markdown
Member

guyharris commented Mar 24, 2026

Speaking of existing solutions to this problem, memcmp(3) refers to consttime_memequal(3), which is even shorter. More generally, it would be nice to find a way not to have to solve such problems in the first place, similarly to how git can work over SSH, but implements neither SSH nor the involved authentication.

Presumably on the server side a "git daemon", or whatever, is run as the ssh command run by the client, so the server doesn't need to implement SSH or authentication, the SSH daemon does; what does it do on the client side, e.g. in the git command?

@infrastation
Copy link
Copy Markdown
Member

On the client side git does similarly, i.e. instead of implementing an SSH client git executes it. See GIT_SSH, GIT_SSH_COMMAND and GIT_SSH_VARIANT in git(1).

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

Labels

Development

Successfully merging this pull request may close these issues.

3 participants