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 unauthorised 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 : ENC An example CAPAB could be the following: CAPAB :QS EX CHW IE EOB KLN HOPS HUB AOPS 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/256 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 :server info "" should be self-explanatory. "" 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 / 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 HOPS AOPS UID ZIP ENC. CRYPTLINK CIPHERS :BF/256 CRYPTLINK SERV irc.server1 :We like IRC! Woo hoo! 4. Server #2 checks to see if it supports BF/256. It does. 5. Server #2 sends: CAPAB :QS EX CHW IE EOB KLN GLN HOPS HUB AOPS UID ZIP ENC CRYPTLINK CIPHERS :BF/256 BF/128 CRYPTLINK SERV irc.server2 :My server is better than yours! CRYPTLINK AUTH BF/256 6. Server #1 checks to see if it supports one of BF/256 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 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/256. 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,v 7.7 2001/12/13 18:31:51 davidt Exp $