ZERO BYTE (the byte at zero offset of the datagram): 00--BF: first byte of an encrypted message within an established connection (that is, the first byte of the obfuscated nonce) C0--DF: means that the actual encrypted message starts with a byte C0..FF, hence the message begins at the next byte E0--FF: a message outside of an established connection Please note the particular value for C0..DF or E0..FF must be randomly generated for each individual datagram. MESSAGES OUTSIDE OF ENCRYPTED CONNECTIONS The least significant half-byte of the Zero Byte is duplicated to form a byte (e.g., 0xE8 becomes 0x88); the second byte is XOR'ed with this value. The result of the XOR is the command: 14 ("Introduce Yourself") request for the peer's credentials 2 1 0 (in future, this might change) 3..363 361 random padding 1A ("I Am") self-introduction 2..33 32 master_pub 34..65 32 master_hash 66..129 64 master_hash_sign 130 1 point id 131 1 "signed-by" code (0x00 or 0xff) 132..183 52 zero point cert (for signed-by==0x00 only) 184..247 64 signature for zp cert (... -- // -- ...) 248..299 52 this point cert 300..363 64 signature for this point cert 57 ("STub") senseless datagram to raise "response credit" 2..127 126 random padding 7E ("TEst") I'm willing to test my NAT (and here's my public key) 2..33 32 the public key 34..127 94 random padding 7F reply on 7E 2..33 32 the kex public key of the responder (the rest is a cryptobox) 34..41 8 nonce 42..57 16 MAC (the rest is encrypted) 58..63 6 your (visible) addr/port, MSBF 64 1 your current stub credit 65 1 reserved (zero) 66..125 60 up to 10 ip/port pairs of the friendly peers 126..127 2 random padding # 9A ("please ask") please ask to contact me (unassoc. peers) # 2..7 6 addr/port to ask, MSBF # 8..127 120 random padding # # # 9C ("please contact") please contact the given address (unassoc. peers) # SENSELESS! One can't "ask" a restricted cone # peer unless it's associated, and there's no # point in asking a fullcone/nonNAT peer for # anything # 2..7 6 addr/port to contact, MSBF # 8..127 120 random padding A5 ("ASsociate") here's my public key for Diffie-Hellman, I know yours (you perhaps know mine, as well, but you could forget it) 2..33 32 the kex public key (the rest is a cryptobox) 34..41 8 nonce 42..57 16 MAC (the rest is encrypted) 58..67 (0) 10 node id 68 (10) 1 point id 69 (11) 1 "signed-by" code (0x00 or 0xff) 70..121 (12) 52 zero point cert (for signed-by==0x00 only) 122..185 (64) 64 signature for zp cert (... -- // -- ...) 186..237 (128) 52 this point cert 238..301 (180) 64 signature for this point cert 302..305 (244) 4 timemark (minutes since Epoch) 306..313 (248) 8 nonce2 314..377 (256) 64 signature for: kex_pubkey+timemark+nonce2 (320) C4 ("Change keY") your encrypted dgram looks strange, here's the actual key 2..33 32 the kex public key 34..41 8 nonce from the err. packet, obfuscated 42..45 4 timemark (minutes) 46..53 8 nonce2 (from our counter) 54..117 64 signature for all the previous 118..127 10 random padding E8 ("error") You sent me something strange or unsupported 2 1 error code 3..127 125 random padding EC ("echo") echo request 2..33 32 the public key 34..37 4 timemark (minutes) 38..45 8 nonce 46..127 82 random padding ED ("echoeD") echo reply 2..33 32 the kex public key of the responder (the rest is a cryptobox) 34..41 8 nonce 42..57 16 MAC (the rest is encrypted) 58..63 (0) 6 your (visible) addr/port, MSBF 64..67 (6) 4 timemark (minutes) FROM THE REQ. 68..75 (10) 8 echo request's nonce 76..85 (18) 10 node_id (our) 86 (28) 1 point (our) 87 (29) 1 minpref (our) 88..95 (30) 8 nonce2 (from our counter) 96..159 (38) 64 signature for the kex key for the echo reply, the kex public key from the request is always used, even when we have an established association with the peer and its key differs; this is because the peer could have restarted thus loosing (changing) its kex credentials, and now tries to reestablish the association with us F0 ("forward") Not used in the present version of the protocol; intended for (encrypted) messages that should be forwarded to another node without decrypting ENCRYPTED MESSAGE STRUCTURE [-16..-1] (not in the message, only in the buffer) the part of the nonce to be zeroed; the byte at [-1] may become a part of the datagram in case the first byte of the nonce is >= 0xC0 0..7 8 nonce (last 8 bytes, obfuscated; the first 16 are 0s) 8..23 16 MAC (the rest is ciphertext) 24 1 message type 25..end ? payload ENCRYPTED MESSAGE TYPES 03 keep alive 25..127 103 random padding 0A please ask to contact me // not implemented yet 25 1 zero 26..31 6 ip/port to ask 32..127 96 random padding 0C please contact 25 1 zero 26..31 6 ip/port to contact 32..127 96 random padding 0E error 25 1 error code 26..127 102 random padding 8x "respond me" -- messages to be responded, resent in case there's no response 25 1 zero 26..29 4 random cookie 30..507 478 (max) the payload 8C do you know this node? 25 1 zero 26..29 4 random cookie 30..39 10 node id 40..237 198 random padding 9x "so I respond" -- responses for the respective 9x 25 1 zero 26..29 4 the cookie from the request 30..507 478 (max) the payload 9C I do/don't know the node 25 1 zero 26..29 4 the cookie from the request 30..39 10 node id 40 1 status: 0:dunno 1:yes (possibly more in future) 41 1 rank: if 'yes', the rank for the node in q. if 'no', the responder's min. rank to be stored in the database 42..73 32 public key (or zeroes for 'no') 74..105 32 hash (or zeroes for 'no') 106..169 64 hsign (or zeroes for 'no') 170..173 4 timestamp (or zeroes for 'no') 174..237 64 sender's signature for 41..173 (or zeroes) B0 Proxy Outbound (packet from proxyuser to proxy server) 25..30 6 ip/port to forward to 31..507 477 (max) the forwarded datagram B1 Proxy Inbound (packet from proxy server to proxy user) 25..30 6 ip/port of the original source 31..507 477 (max) the forwarded datagram Dx data (carries an encapsulated IPv6 packet) 24 1 0xD0 | ((part_cnt-1) << 2) | part_num 25..27 3 peer-local sequential number (wraps) 28..475 448 (max) the payload The max. payload size is choosen keeping in mind that we should remain to be able to enclose our packets (full enclrypted dgrams) into other packets and still not overcome the 508 bytes limit. The 448 bytes limit for the payload (476 for the whole dgram) leaves 32 bytes for the encapsulating dgram. Okay, 8 bytes of nonce, 16 bytes of MAC, 1 byte msg type, 4 bytes to identify the forwarging stream somehow, and remember that one byte to escape in case the obfuscated nonce starts with 0xC0..0xFF... well, still 2 bytes are left until The Limit. 4+2 may also be the ip:port, but in this case we'll have no reserve. Besides that, we keep in mind that one day we may implement the MTU path discovery as it should be, and after that we'll use dgrams of greater size, such as 1500 bytes. So we implement reassembling of dgrams without imposing any size limits. Only the sending procedures are affected with the limits. MESSAGE EXCHANGE *************** * Establishing crypto association Client Server echo request (EC) ---> <--- echo reply (ED) (*if* client doesn't know the server's node) [failure] (XXX to be changed) (*if* client has the server's node, but not the server's point) please introduce (14) ---> <--- i am (1A) (*if* the client has the server's point cert, initially or after 1A) associate (A5) ---> (*if* the servers knows at least the node of the client) <--- keep alive (enc.03) [ok] (*if* the server doesn't know the client's node) [failure] (XXX to be changed) *************** * Checking NAT Client Server Sibling(s) stub (57) ---> * stub (57) ---> * stub (57) ---> * stub (57) ---> * stub (57) ---> * test (7E) ---> * * <--- test R (7F) plz cnt (enc.0C) ---> * * <---------------------------- stub (57) (*if* client received all expected dgrams) [done] (*if* client's waiting timed out, only got the server's reply) ("second stage") echo rq (EC) ----------------------------> * * <---------------------------- echo rpl (ED) [done] *************** * Generic messages Messages of the types "error" (E8) and "change key" (C4) are sent whenever it is appropriate, which effectively means something went wrong. The C4 type is used in situations when an incoming _encrypted_ datagram can not be decrypted. It is used as indication for the error, but, unlike the E8 type, it contains the actual KEX public key of the party which detected the error, and the key is signed by the point's key together with the current timemark. In (a very common) case when the error was caused by restarting of the fedaserv instance, this makes it possible for the partner to recover the cryptographic association with a single datagram of the A5 type ("associate"): Alice Bob (any encrypted dgram) ---> <--- change key (C4) associate (A5) ---> <--- keep alive (enc.03) [ok] Unlike the C4 type, a datagram of the E8 type ("error") contains no authentication info, so it can not be used for automated recovery of any kind: otherwise, it would be possible for anyone on the Internet to spoof such a datagram and fool random fedaserv instances into believing something goes wrong and there's a need for recovery, thus effectively breaking existing and normally functioning associations. Hence, E8 type dgrams can only serve as a source of information for human operators, and they are only sent in situations the software has no recovery procedure for the error in question (as of now this means all errors except the inability to decrypt an encrypted dgram). The only thing the receiving party does upon receiving them is logging a message. *************** * Established crypto association There are no exchange procedures for the case of an established cryptographic association; each type of the encrypted datagrams is used in the respective situation and is expected to be reacted upon accordingly.