OK, finally got the time to answer this. :-) That's good stuff.
[Static keys, KX procedure]
> This leaves the problem of handling the situation where an NK_ACK
> reply is lost. The receiver is expecting to see the new dynamic key,
> but the sender doesn't realize that and continues using the old one.
> To solve this problem, the receiver must store two dynamic keys,
> both the old one and the new one. Each incoming packet must be
> decrypted first with the new key; if the CRC check fails then it must
> be decrypted using the old key. Receipt of a packet that uses the new
> dynamic key is the indication that the old key can be erased. If the
I've thought of this in the beginning of the project several years
ago, and decided that I didn't want to decrypt packets twice mainly
for efficiency reasons. (386/25 and all that ;-) This reasoning may
well be bogus today, but I still think it is inelegant.
In fact when we try two keys, we can as well lose the static-key flag
in the IV and try three keys. This would remove another little
ugliness from the crypto POV. Of course that is incompatible (your
proposal doesn't strictly change the protocol; with mixed protocols it
leads to massive packet loss after a KX failure but that should be
able to heal itself eventually. At least I think so).
I'm not really sure where to go here. When a real protocol overhaul
(i.e. which would introduce protocol version 5) is necessary some work
in this area will have to be done, esp. to show that it remains stable
in all packet loss scenarios.
OTOH I've put more energy in PKCIPE the last time I did major
development, precisely to do away with the key longevity problem.
[Replay attacks, timestamps]
> The proposed solution is to make timestamps mandatory for out-of-band
> packets, and perhaps even decrease the recommended window of agreement
> to 10 seconds, and to do this in a way that does not require the
> system clocks to be synchronized. This is easily accomplished by
> having each host keep track of the offset between its clock and its
> peer's. The timestamp fields in the packets are then set by adding
> the offset to the current system time.
This looks too complicated to me. Better make the window even less
than 10 seconds and require the peers to be synchronized. I run NTP on
every box I have, for the time when I used CIPE to connect machines
across the country, one of which was a cheap router on a nonpermanent
connection, I even used a homebuilt DCF77 clock on that box. There are
too many applications already which require synchronized clocks and
proper synchronization is cheap enough (again, with the current state
of hw/sw machinery at least) to not allow slack here.
> The sender of the original request receives the reply back at time C.
> >From this, the sender computes its offset value as B - A and the
> peer's offset value as C - B. The sender can then create an encrypted
If you require precision, this isn't enough. Think lost, duplicated or
severely delayed packets - you'd have to deal with the same problems
as NTP here. (Of course, it's not that important for precision in the
seconds range, but it carries the potential for subtle errors.)
Putting seriously more complexity into the protocol to solve a problem
which has a cleaner solution elsewhere doesn't look that good to me.
> Finally, there is the possibility that the system clock on one of the
> hosts may undergo a large discontinuous jump, for example if the
> system administrator resets the system time. This would disrupt
> CIPE's encrypted communications. (Note that small changes in the
It does already (with timestamps turned on), but I don't worry much
about that. Just restart the CIPE daemons in this case.
[Packet stealing by replay]
> [Still, the gold standard for accepting changes in secured values like
> the peer address runs more like this: A new address is accepted only
> if it is also stored in encrypted form within the packet itself. A
> new packet type could be defined for this purpose. With this
To prevent the packet stealing attacks, this would be the way to go.
> proviso, an attacker would not be able to deceive the victim, since it
> could not encrypt the forged address. An objection is that often a
> host does not know its own UDP address (if it is behind a firewall
> that uses NAT, for example). That presents no difficulty; we can add
This would be a job for STUN instead of creating our own solution
(which basically does the same thing as STUN) - when/if that becomes
Another concern why STUN or similar external solutions are desirable
is that we're currently unable to connect two NATed hosts, even with
PKCIPE. This requires a mediator, and even though writing one is easy
(the core STUN protocol is little more than ping, just the
authentication stuff makes it complex) many users are in a situation
where they can't deploy arbitrary software on a permanently connected
> timestamp. If the roving host is aware that its address has changed
> then it can immediately create such a packet; otherwise communications
> will be disrupted in one direction for some period of time. Perhaps a
Any host is aware of carrier address changes, this was added in 1.4 to
better deal with dynamic addresses. To initiate a ping or KX after
each address change should be easy.