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!)