3 ms·
Great to see protocol versioning over negotiation. I don’t think replacing OpenSSH is as important as wireguard replacing OpenVPN but it’s up there. Protocol t
by lvh 8y ago
Great to see protocol versioning over negotiation. I don’t think replacing OpenSSH is as important as wireguard replacing OpenVPN but it’s up there.
Protocol tasting notes:
- If you’re going to dole out PSKs, why care about signatures? If you’re going to dole out PSKs, why are they separate from the knock PSKs? (You sort of address this by sharing knock PSKs are per server and handshake PSK is per pair. But if I have a PSK per pair anyway, why not use it for knocks?)
- the knock protocol looks like semantically it wants a PRF. Is there a reason not to make it a PRF?
- Why isn’t this a Noise instantiation?
- Why sign instead of 3DH?
- Why is PBKDF2 involved in the PSK (preshared key)?
Of these, not using a PRF feels like a smell (probably not a vuln, but why would you choose to have that in your spec?). On the other hand, having PSKs and then choosing to have PBKDF2 involved (to stretch a passphrase, I guess?) and then having a key exchange anyway is really strange to me. The point of a key exchange protocol is to get a shared secret. But the protocol starts by assuming you already have a shared secret! Just use that already. Plugin in a PRF and the current time and some randomness and BAM: fast trustworthy crypto forever.
Of course, there's a reason we don't use PSKs all over the place: it means that instead of exchanging N public keys you have to exchange N^2 secret ones. People do it, but it's not the default. I'm fine with something that uses PSKs and something that uses public keys, but I don't understand why a system would have both. You get the operational complexity of PSKs and the performance of KEXes. Why bother? (I understand that the protocol says the PSK is to make it post-quantum, but you'd get identical post-quantum properties if you just skipped the KEX!)
- galadran 8y agoThe Noise framework (and Wireguard) deliberately support the combination of psk and public key authentication. One clear benefit is that you get redundancy against a failure in either mode. If your DH implemention is broken, the attacker still has to compromise your shared secret. Alternatively if the attacker compromises your shared secret, they still have to break your public key crypto. In short, its an excellent hedge against user or implementor error. Less tangibly, it can prevent an adversary from recording your traffic now, waiting until Quantum Computers are practical, breaking your public key crypto and reading your messages. Sure, you can't just slap both modes together and claim the adversary has to break both, some care is involved, but it absolutely isn't strange at all. tl;dr there are plenty of good reasons to use a combination of modes. Both Noise and Wireguard have built on support for strengthening public key crypto with psks.
- lvh 8y agoI get the general argument, but the spec doesn't really try to make that case. The default knock and PSK are (PQ) tiny: they appear to be 20 base32-encoded bytes or 96 bits of entropy. If they were being used in the same sense as Wireguard/Noise's PQ, I'd expect them to be 256 bits. EDIT: I take it back: the keys _used_ to be 96 bits (example given in the protocol description), but are now 256 judging by the keygen code. Apparently (I'm spelunking in the bug tracker) they were short once because there was an attempt to make them diceware-style verbally transmittable? Regardless: at least it looks like an effective PQ measure assuming the key derivation works. (Generally hedging against DH snafus makes a lot of sense to me, hedging against clients who can somehow manage to hold on to one kind of key material but not another is less convincing. I guess you could have P-256 on a smartcard and PSK on disk or something?)
- lvh 8y agoFWIW: I followed up on the "slapping both modes together" part: if you assume both parts work individually, PBKDF2's them together as part of the transport rekeying: https://github.com/oxy-secure/transportation/blob/9cf9356ad50a5b933529d824a480179b4ffd0460/src/encrypted_transport.rs#L63 https://github.com/oxy-secure/transportation/blob/9cf9356ad5... The code relying on that just extends the generated key with the statically found key, so it appears to be fine as long as you just chuck enough entropy in. So it appears an empty shared secret would just do what you'd expect: just the DH bit.
- lvh 8y agoAh! I figured out the underlying reason: in the default configuration the PSK isn't per-peer-pair, it's per server. That makes a ton more sense! You get to keep the relatively simple key distribution mechanism, keep identity despite a team-shared PSK (that's what signing solves), and you get PQ resistance. (The problem this addresses is a passive observer who eventually gets a quantum computer, but can't pop any machines to just steal the PSK or whatever.)
- lvh 8y agoSomething else I didn't understand until I read the code: I couldn't figure out why the ephemeral key would be Ed25519. Turns out it's not, that's probably a typo: https://github.com/oxy-secure/oxy/blob/571ef12199f8b0f3eca5559f031b572677b8ab86/src/core/kex.rs#L57 https://github.com/oxy-secure/oxy/blob/571ef12199f8b0f3eca55...
- lvh 8y agoIf anyone knows rust better than I do: https://github.com/oxy-secure/oxy/blob/571ef12199f8b0f3eca5559f031b572677b8ab86/src/core/kex.rs#L280 https://github.com/oxy-secure/oxy/blob/571ef12199f8b0f3eca55... What is the point of panic! after exiting the process?
- steveklabnik 8y agoThere isn’t one. They even had to suppress a warning about how the code can never be reached.
- lvh 8y agoHah, OK then :-) I figured there might be a unit-testy reason or something -- where you can temporarily disable panics and patch out process exits. Thanks!
- steveklabnik 8y agoNot that I'm aware of. Let's see if there's a good reason I'm missing: https://github.com/oxy-secure/oxy/pull/117 https://github.com/oxy-secure/oxy/pull/117
- lvh 8y agoI think (from issue tracker spelunking) PBKDF2 got added in because at some point the PSKs weren't very strong and intended to be human-transmittable. They're still in the transport protocol. I'm not sure why, but I guess for some parameter choices it could improve forward secrecy? (That is: if you break a KEX at t=0 now you have to compute a hard function a bunch of times to make it to t=now if sessions are long-held? Seems far-fetched but...) It's really nice to see protocols where people use memo fields to make sure one key can't be derived for another purpose though, and that is a feature you get out of PBKDF2 (but not only PBKDF2, hence my question) :)