Description of the protocol used by PKCIPE

This is a protocol to ease configuration of CIPE links. It removes the
need for secret keys and deals well with dynamic carriers.

This protocol performs the following tasks:
- Do a Diffie-Hellman key exchange
  Generates keys for this protocol and for CIPE
- Tell each other side the identity
- Give a RSA public key signature as authentication
- Negotiate parameters for CIPE

Most of the protocol runs encrypted. It is feasible to do this over an
insecure link.

The PKCIPE protocol carries a version number. This document describes
version 2.

Two PKCIPE instances communicate over a TCP connection. The addresses
used on the connection need not coincide with the addresses for which
the CIPE link is being configured. There is no distinction between
server and client. Data is sent in packets which are encapsulated as
described below. Each packet received must be answered with exactly
one packet sent except where noted below. As soon as the connection is
established, each side sends a PKT_MAGIC identification packet. The
connection is closed by any side after receiving a PKT_DONE packet.

Packet encapsulation

Each packet has the following format:
Header
 1 byte marker
 2 byte length
Data
 n byte data
 1 byte check

The marker always has the value 0x2a.
The length is sent in big-endian format, each byte is XORd with the
value 0x50. The minimum length is 1 and the maximum is 32766.
The length gives the length of the data field not counting the check field.
The check is the sum of all bytes in the data field mod 256.

Encryption of packets uses the RC4 stream cipher with different keys
in each direction. The encryption covers the data with check field,
the header is not encrypted.

Certain packets are covered by a signature, which applies to the data
with check field.

The first byte of the data field indicates the packet type. Packet
data starts with the second byte if applicable.

When packet data contains a BIGNUM, this is represented by the I2OSP
transformation defined in [PKCS1], with the length implied by the
packet length.

Strings contained in packets need not be null-terminated.

Example: a packet with type 0x33 and packet data 0x44,0x55,0xaa,0xbb is
encoded like this (hex):
2a 50 55 33 44 55 aa bb 31
                        ^--check---------------------+--covered by signature
         ^-----------------data----------------------+  and/or encryption
   ^-----------------------length (5 xor 5050)
^--------------------------marker

The defined packet types carry an indication about whether they have
to be signed. This is given by the upper two bits:
bit 6: if set, include this sent packet in signature.
bit 7: if set, include this _received_ packet in signature. (Reverse sign)
No packet type may have both signature bits set.

Protocol phases

The protocol consists of three phases: setup, negotiation, finish.
After connecting, both sides immediately start the setup phase.
In this phase they send/receive these packets in order:

PKT_MAGIC type 0x43, data contains ASCII text: 
indicates the version of the protocol and software. The protocol
version each side speaks is given as a decimal number greater than
zero after the first slash character.[1] The remaining stuff is
comment, it is expected to contain the software version number.

The protocol version actually spoken by both sides is the smaller of
the indicated protocol versions. If this results in a value
unacceptable to one side (e.g. because it knows that version is
deprecated) it may drop the connection and retry using a smaller
value.

PKT_NONCE type 0x91, data contains at least 8 random bytes:
random value used to seed the key generator and to mutually verify the
signatures (this packet has to be signed by the recipient, which makes
any sort of replay of Diffie-Hellman keys impossible).

Both sides generate a "seed" value of 16 bytes by XORing both nonces
(own and received), padded at the end with nulls or truncated to fit.
This "seed" value is used in the key generator described below.

PKT_DHKEY type 0x52, data contains a BIGNUM:
gives the Diffie-Hellman public value.

Upon reception of this packet, both sides perform the Diffie-Hellman
shared secret computation. The prime and generator to be used are fixed
and defined in the file dhkey.h. (If they become deprecated a new
protocol version will have to be defined.)

Both sides then compute three blocks of key data, each block of length
20 bytes, using the P_SHA1 function with the shared secret (of length
128 bytes, as the DH prime is 1024 bits long) as "secret" and the
seed value computed above from the PKT_NONCE packets as "seed".

The P_SHA1 function is defined as follows:
 A(0)      := seed
 A(n)      := HMAC_SHA1(secret, A(n-1))         for n>=1
 P_SHA1(n) := HMAC_SHA1(secret, A(n) + seed)    for n>=1
This is the function of the same name used in TLS ([TLS], section 5).[2]
[HMAC, SHA]

P_SHA(1) becomes the RC4 sending key for the side whose public DH
         value is numerically bigger.
P_SHA(2) becomes the RC4 sending key for the side whose public DH
         value is numerically smaller.[3]
P_SHA(3) becomes the "static" key for the CIPE link.

Before sending the next message, both sides turn on packet encryption.

PKT_IDENT type 0x53, data contains a number in 8 hex digits followed
by the identity (name) of the sender:
Identifies the sending side. The number given is a simple checksum
over the sender's public key, to allow for quick verification that the
key is known. This sum is computed as follows:
1. Generate the I2OSP transform of the public modulus.
   (In this protocol version, only RSA keys are used.)
2. Take this data as an array of 4-byte big-endian integers.
   Discard the last 1..3 bytes if the length is not divisible by 4.
3. Compute the XOR of all of these integers.

PKT_SIGN type 0x14, data contains a signature: 
Gives the signature of all signed packets sent/reverse-signed packets
received so far. The signature is built using the RSASSA-PKCS1-V1_5-SIGN 
operation [PKCS1], i.e. an RSA-signed message digest containing
embedded information on the hash algorithm used. It is recommended
to use SHA1.

After successful verification of the signature, both sides enter the
negotiation phase.

[XXX Still to be written.]

The finish phase begins when one of the following conditions are true:
1. The negotiation is complete. A PKT_READY packet is sent.
2. Any error has been detected (from either the setup or the negotiation 
   phase). A PKT_ERROR packet is sent.

PKT_READY type 0x15, data is comment string:
Indicates that the actual ciped has been started. Requests the peer to
do likewise if not already done.

PKT_ERROR type 0x01, data is comment string:
Indicates an error has occurred.

When either of these are received, PKT_DONE is sent and the connection
is closed.

PKT_DONE type 0x02, data is comment string:
Indicates the connection is finished and about to be closed.

There is another packet type defined, which is handled specially:

PKT_DEBUG type 0x00, data is comment string:
This packet is logged but otherwise ignored by the recipient. It can
occur at any time but must be immediately followed by another packet
(i.e. the sender of this packet must not wait for input after
sending). It generates no answer on its own.

Footnotes:

[1] The implementation sends packets with the length 0x1b, the first
data bytes being "IPE/", and the last data byte 0x2a.
Thus the first bytes actually sent over the wire look like this in ASCII:
*PKCIPE/2 0.03 development   *

[2] TLS combines this function with a similar one based on MD5 and
uses the XOR of both as a result. It was decided for this protocol to
save the overhead and consider SHA1 alone as good enough until it gets
broken, in which case a new version will have to be defined.

[3] If both DH public values are equal, given they are random 1024 bit
numbers, this indicates a severe problem with both(!) random number
generators. In this case the proper action is to dump core or even shut
down the system before the bogus RNGs can do more damage.

Bibliography:

[HMAC]  Krawczyk, H., Bellare, M., and R. Canetti, "HMAC:  Keyed-
        Hashing for Message Authentication," RFC 2104, February 1997.

[PKCS1] Kaliski, B., and J. Staddon: "PKCS #1: RSA Cryptography
        Specifications, Version 2.0," RFC 2437, October 1998.

[SHA]   NIST FIPS PUB 180-1, "Secure Hash Standard," National
        Institute of Standards and Technology, U.S. Department of
        Commerce, Work in Progress, May 31, 1994.

[TLS]   Dierks, T., and C. Allen: "The TLS Protocol, Version 1.0",
        RFC 2246, January 1999.

$Id: PKCIPE-Protocol,v 1.2 2000/11/30 22:12:40 olaf Exp $
