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:


/* 0x used by the encrypted part */

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


1B   ("node Introduction Process request") here's the cert of my node
	2..33		32	master_pub
	34..65		32	master_hash
	66..129		64	master_hash_sign
	130..131	2	0/0 (in future, this might change)
	132..139	8	cookie (req. id)
	140..203	64	random padding

1C   ("Introducton Challenge") please solve this first
	2..3		2	0/0 (in future, this might change)
	4..11		8	cookie (req. id)
	12..75		64	challenge descriptor (server-defined)
	76..203		128	4x32 arrays to take the hashes

1D   ("Intro challenge Done") here's the solution, here's the cert
	2..33		32	master_pub
	34..65		32	master_hash
	66..129		64	master_hash_sign
	130..131	2	0/0 (in future, this might change)
	132..139	8	cookie (req. id)
	140..203	64	challenge descriptor
	204..331	128	4x32 arrays -- the hashes taken

1F   ("Intro Fulfilled") Intro accepted (or the node already known)
	2..3		2	0/0 (in future, this might change)
	4..11		8	cookie (req. id)
	12..21		10	the node ID we've just accepted 
	22		1	the rank as we computed it
	23..127		105	random padding


51   ("Suggest to Introduce") List of certhubs to introduce your node to
	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..65	 	8	cookie from the A5 dgram
	66		1	zero (may change in future)
	67		1	certhubs count (0..10); 0 means this speaker
				is willing to accept the intro on its own
	68..127		60	up to 10 ip:port pairs of certhubs, the
				unused resting space is zeroed



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


/* 8x used by the encrypted part */

/* 9x used by the encrypted part, the following two "commented out" types
   were never implemented */

# 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	cookie (was "nonce2", proven to be senseless)
	314..377 (256)	64	signature for: kex_pubkey+timemark+nonce2
		 (320)


/* Bx used by the encrypted part */

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, obfuscated)
	54..117		64	signature for all the previous
	118..127	10	random padding



/* Dx used by the encrypted part */

E8   ("error")  You sent me something strange or unsupported
	2		1	error code
	3..127		125	random padding

E9   ("error+")  You sent me something strange, but I know the cookie
	2		1	error code
	3		1	type (byte 1) of the command caused error
	4..11		8	your nonce, cookie or first 8 bytes of padding
	12..127		116	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


    Please note message type codes are unique across the border of
    non-encrypted / encrypted parts of the protocol; please keep this
    property forever, as error handling partially depends on it.  Guys,
    there will never ever be 256 different dgram types in this protocol...
    errr... otherwise, it will die under its own weight.


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..33		8	random cookie
	34..507		474 (max) the payload


8B		please check this hash for me
	25		1	zero
	26..33		8	random cookie
	34..65		32	master_pub
	66..97		32	master_hash
	98..161		64	master_hash_sign
	162..241	80	random padding (get as long as 0x9C response)



8C		do you know this node?
	25		1	zero
	26..33		8	random cookie
	34..43		10	node id
	44..241		198	random padding (get as long as 0x9C response)



9x		"so I respond" -- responses for the respective 9x
	25		1	zero
	26..33		8	the cookie from the request
	34..507		474 (max) the payload


9C		I do/don't know the node
	25		1	zero
	26..33		8	the cookie from the request
	34..43		10	node id
	44		1	status: 0:dunno 1:yes (possibly more in future)
	45		1	rank: if 'yes', the rank for the node in q.
				      if 'no', the responder's min. rank to
				      be stored in the database
	46..77		32	public key (or zeroes for 'no')
	78..109		32	hash (or zeroes for 'no')
	110..173	64	hsign (or zeroes for 'no')
	174..177	4	timestamp (or zeroes for 'no')
	178..241	64	sender's signature for 45..177 (or zeroes)

		encrypted part length is 242-25 = 217 bytes

		The signature may look redundant here, as the dgram is
		encrypted already, which means nobody but the peer
		could prepare it; however, the idea here is to store the
		signature as evidence we really trusted this peer (that
		is, nobody injected our 'database' with this cert).
		Unfortunately enough, saving this info is not implemented :-)



9E		Error (with your cookie)
	25		1	zero
	26..33		8	the cookie from the request
	34		1	error code
	35		1	type (byte 24) of the command caused error
	36..127		92	random padding




B0		Proxy Outbound (packet from proxy user 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 OR point)

	please introduce (14)	--->

				<---	i am (1A)

(*if* the client has the server's point cert, initially or after 1A)

	associate (A5)		--->

		(*if* the server knows at least the node of the client)

				<---	keep alive (enc.03)

				[ok]

		(*if* the server doesn't know the client's node
			and is unable to verify it immediately)

			(ask all trustncc's)

				<---	consider introducing there

				[protocol status reset]


(*if* the client doesn't know the node, but has active trustncc peers
	and didn't ask them about this node recently, and/or we have an
	active introducer peer)

	(send requests to all active trustncc's and one of the introducers)

				[protocol status reset]



***************
* 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.

