339 lines
13 KiB
Text
339 lines
13 KiB
Text
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 :<other supported capabilities> 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 <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 HOPS AOPS UID ZIP ENC.
|
|
CRYPTLINK CIPHERS :BF/256
|
|
CRYPTLINK SERV irc.server1 <keyphase> :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 <key> :My server is better than yours!
|
|
CRYPTLINK AUTH BF/256 <base64-encoded verification key>
|
|
|
|
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 <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/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 1.2 2002/08/13 14:45:05 fishwaldo Exp $
|