                                    CRYPTLINK Encrypted Server Link Protocol
                                    ========================================
  (Loosely based on draft by A1kmm)
  (Rewritten by David-T, einride, vulture, and jdc)

0.1 - Conventions of this document
----------------------------------

	* "MUST" means that a server is not compliant unless it does this.
	* "MUST NOT" means a server is not compliant if it does this.
	* "SHOULD" means that a server is at most conditionally compliant
	  if it does not do this.
	* "SHOULD NOT" means that a server is at most conditionally
	  compliant if it does this.
	* "MAY" means that a server may choose whether or not to do this.


1.1 - Goal of this protocol
---------------------------

	To reduce the risk of attacks relating to password sniffing,
	replay attacks, or connection hijacking, in turn permitting
	unauthorized access to server privileges.

1.2 - Background of this protocol
---------------------------------

	This protocol is based on the IRC protocol as described in RFC1459,
	and extensions implemented on EFnet as described in other documents
	available in this directory (doc/), and on the WWW.

	Any encrypted strings which are transmitted in IRC commands in
	accordance with this document shall be base64 encoded, with the
	most significant bits of the most significant byte transmitted
	first, followed by bits/bytes of decreasing significance.  However,
	the encrypted link itself will be 8-bit, without no encoding.

2.1 - Configuration changes
---------------------------

	Every server which supports encrypted links has a 2048-bit RSA
	private key stored in a configuration file.  Care must be taken
	to ensure this file is accessible only to the ircd user.  For
	every link to another server that supports encrypted links, the
	public component of that server's RSA key is stored instead of the
	traditional password or password hash.

	A server which is configured to make an encrypted link to another
	MUST NOT fall back on any other authentication scheme, regardless
	of what the remote server sends or does.


3.1 - Changes to the CAPAB command
----------------------------------

	The first command sent by a server over an encrypted link MUST
	be a CAPAB command.  The CAPAB command MUST include the
	ENC capability.  The syntax would be as follows:

		CAPAB :<other supported capabilities> ENC

	An example CAPAB could be the following:

		CAPAB :QS EX CHW IE EOB KLN HUB ENC ZIP

        Note that ENC is not required to be the last capab.

	The maximum allowable key length permitted for the encryption
	cipher is 512 bits, as only 64 bytes of random data for the
	key is available.

	Servers which support regeneration of session keys MAY also
	include the DK ('Dynamic Key') capability.

3.2 - New 'CRYPTLINK CIPHERS' command
-------------------------------------

	To prevent admins having to identically configure each end of
	the link, the ircd SHOULD allow the admin to specify a list
	of ciphers to be supported on a per link basis and/or a global
	default.

	The second command sent over a CRYPTLINK enabled link MUST be the
        CRYPTLINK CIPHERS command, to inform the remote server what ciphers
	are supported by this end of the link:

		CRYPTLINK CIPHERS :cipher1/keylen cipher2/keylen, ...

	For example:

		CRYPTLINK CIPHERS :BF/168 BF/128 3DES/156

        The ciphers which are available as of the date this document was
	written are listed in doc/README.openssl.

	All servers MUST, as minimum, support BF/128 encryption; admins
	MAY choose to use another cipher which is available.

	If no ciphers are supported on BOTH servers, the receiving
	server (the server which was connected to) should send back an
	error response, instead of returning a CRYPTLINK CIPHERS command
	of its own.  See Section 3.5 ("Error Responses") for more
	information on the process for doing this.

3.3 - Key Generation
--------------------

	To initiate an encrypted link to another server, each server
	is required to generate a 512-bit random key, of which a portion
	will be used to decrypt all data received by the server.  This key
	MUST be generated by a cryptographically strong PRNG.

	This key should be stored, then encrypted to the server's private
	key, encrypted to the remote server's public key, then base64 encoded
	for transmission to the remote server.

3.3 - Link Establishment
------------------------

	Once the initiating server (server A) has connected to the
	remote server (server B), it MUST send the CAPAB command,
	listing its capabilities (including the new ENC capability).

	It MUST then send a CRYPTLINK CIPHER command, as described above.

	It MUST then send a CRYPTLINK SERV command using the following
	syntax:

		CRYPTLINK SERV <irc.server.name> <key> :server info

	"<irc.server.name>" should be self-explanatory.  "<key>" is the
	base64-encoded key.  "server info" is the server's M-line.

	Servers MUST NOT send a PASS or initial SERVER command over an
	encrypted link.  However, SERVER commands are still used to
	introduce remote servers during the net burst, and as they link
	to the network.  All encrypted links MUST support the
	TS protocol (as normally indicated by PASS ... :TS).

	On receiving the CAPAB command, server B MUST send its own
	CAPAB/CRYPTLINK CIPHER/CRYPTLINK SERV commands and decrypt and
	verify the signature on the key, unless there is an error
	processing one of the received commands, in which case, an error
	should be sent instead -- see Section 3.5 ("Error Responses").

	Server B should then select a cipher to be used bi-directionally
	for data encryption.  The server MAY determine the 'preferred'
	cipher by using the order in which the ciphers were listed in
	each CRYPTLINK CIPHER command, or simply select the first cipher
	found to be compatible with both ends.

	Then Server B must interleave the received 64 byte key with its
	generated 64 byte key as follows:

		R[0]G[0]R[1]G[2] ... R[62]G[62]R[63]G[64]

	It must then (using RSA) encrypt this key to its own private key
	(to sign the data), then encrypt it to Server A's public key.

	It should then send a CRYPTLINK AUTH command as follows:

		CRYPTLINK AUTH <cipher>/<keylen> <base64-encoded new key>

	Once this command has been sent, the link MUST switch to being
	encrypted.  All future data sent over the link will be encrypted
	using the selected symmetric encryption cipher, with the key
	used to encrypt data being generated by using the first N bits,
	where N is the key length of the negotiated cipher, from:

		R[0]G[1]R[2]G[3] ... R[60]G[61]R[62]G[63]

	At this point, Server B SHOULD send an SVINFO command, followed by
	a normal net-burst.

	If the CAPAB lines exchanged indicated that both servers support
	ZIPLINKS for this link, the data will be "zipped" immediately
	before encrypting it.  The data will start to be "zipped" after
	the CRYPTLINK AUTH command is sent (i.e., at the same time as
	encryption).

	After receiving a CRYPTLINK AUTH command Server A MUST decrypt the
	key returned by Server B and ensure it is correct - taking care
	to use the correct key to compare (i.e. G[0]R[0] ... G[63]R[63]).
	If it is not, the server SHOULD notify online admins/IRCops, and
	MUST drop the link.

	Server A will then send its own CRYPTLINK AUTH command, and switch
	to an encrypted link as above.  It SHOULD then send an SVINFO
	command, and a normal net-burst.

	Server B MUST also validate the CRYPTLINK AUTH response as above.

3.4 - Key Regeneration
----------------------

	Although a capability (DK) to indicate support for dynamic key
	regeneration has been defined, the protocol extensions required
	to support this ability have not yet been defined.

3.5 - Error Responses
---------------------

	There are many possibilities of failure/error during the
	negotiation process.  Due to the vast diversity of these
	errors, a generic error response mechanism should be implemented.

	The stock ERROR command is used to spit out errors regarding
	all sorts of errors.  Example:

	Example:

		ERROR :No compatible ciphers enabled.  Aborting Link.

	This response MUST be sent immediately after any error is
	encountered.  For example, if the cipher negotiation phase
	fails, the receiving server MUST send an ERROR response once this
	is detected, and the socket MUST be closed.

	The output to the ERROR command can be anything.  Do not assume
	all ERROR messages for CRYPTLINK failures will be the same; they
	MAY be changed by administrators.

	See Section 4.0 ("Communication Phase Examples") for some more
	examples.

3.6 - The Validation Mechanism
------------------------------

	It is important to understand how the validation process
	works.  Section 3.2 ("Key Generation") briefly touches on
	this subject.

	Both servers have a pair of keys on their file system: a PUBLIC
	key, and a PRIVATE key.

	Each server should have a copy of the others' PUBLIC key.

	Herein we will refer to each server individually as "Server A" and
	"Server B."  In this example, Server A is connecting to Server B.

	Server A connects to Server B, and sends CAPAB, followed by
	CRYPTLINK CIPHER.

	Server A then generates a unique 512-bit key phrase.  This key phrase
	is generated from a 64 bytes of random data taken from what is
	referred to as a PRNG ("Pseudo-Random Number Generator").  A PRNG
	could be something like /dev/urandom or something like the EGD
	("Entropy Gathering Daemon").

	The key phrase is encrypted to Server A's own PRIVATE key, to sign
	the data.  They key is then encrypted using Server 2's PUBLIC
	key to prevent anyone sniffing the connecting from determining
	the session key.

	This keyphrase is sent to Server B during the CRYPTLINK SERV
	phase.

	After selecting a cipher, Server B takes the keyphrase, and
	decrypts it using it's own PRIVATE key.  If the decryption fails,
	an ERROR is sent, and the connection is dropped.  The signature
	is then verified by decrypting the data with Server A's PUBLIC key.

	Server B then sends its own CRYPTLINK SERV command as above.

	Server B then combines the data with the locally generated
	key with the received key as defined above[1], and signs
	and encrypts this new key in the same way as the original, and
	sends it to Server A.

	Server A then decrypts the key, and verifies it matches the
	expected values, based on the key it generated, and the key
	received from Server B.  If it mismatches, Server A assumes
	Server B could not decrypt Server A's data, and thus is not
	in possession of Server B's private key.

	If the data matches, the authentication is legitimate, and
	the servers officially link up.

	If the data does NOT match, then someone is being naughty.
	In this case, an ERROR is sent, and the connection is dropped.

4.0 - Communication Phase Examples
----------------------------------

  Server #1 connects to Server #2
  ===============================
     1.  Server #1 initiates connection to Server #2 on port 6667.
     2.  Server #2 answers on port 6667.
     3.  Server #1 sends:

       	    CAPAB :QS EX CHW IE EOB KLN GLN UID ZIP ENC.
	    CRYPTLINK CIPHERS :BF/168
	    CRYPTLINK SERV irc.server1 <keyphase> :We like IRC! Woo hoo!

     4.  Server #2 checks to see if it supports BF/168.  It does.
     5.  Server #2 sends:

            CAPAB :QS EX CHW IE EOB KLN GLN HUB UID ZIP ENC
	    CRYPTLINK CIPHERS :BF/168 BF/128 
	    CRYPTLINK SERV irc.server2 <key> :My server is better than yours!
	    CRYPTLINK AUTH BF/168 <base64-encoded verification key>	    

     6.  Server #1 checks to see if it supports one of BF/168 or BF/128,
         and selects an outgoing cipher (BF/128).
     7.  Server #1 decrypts the key, and validates it.  It's correct.
     8.  Server #1 sends:

	    CRYPTLINK AUTH BF/128 <base64-encoded verification key>

    12.  Server #1 now enters zip/encryption mode, and sends a net burst.
    13.  Server #2 decrypts the key, and validates it.  It's correct.
    14.  Server #2 now enters zip/encryption mode, and sends a net burst.

  Server #1 connects to server #2, cipher fails
  =============================================
     1.  Same as Steps 1-3 of the above example.
     4.  Server #2 checks to see if it supports BF/168.  It does NOT.
     5.  Server #2 sends:

           ERROR :CRYPTLINK - No compatible ciphers enabled.  Aborting Link.

     6.  Server #1 is aware of the error, logs it, and/or informs
         administrators/IRCops on the server of the cipher failure.
     7.  Server #2 closes the socket.


  Server #1 connects to server #2, CRYPTAUTH fails
  ================================================
     1.  Same as Steps 1-6 of the above example.
    11.  Server #1 decrypts the key, and validates it.  It's INCORRECT.
    12.  Server #1 sends:

           ERROR :CRYPTLINK - Verification failed.  Home, James.

    13.  Server #1 is aware of the error, logs it, and/or informs
         administrators/IRCops on the server of the key mismatch.
    14.  Server #1 closes the socket.

$Id: cryptlink.txt 33 2005-10-02 20:50:00Z knight $
