Subject Crypto Extentions to Remote Protocol
Author Jim Starkey
I'm posting this proposal to both the devel and architecture lists
because of general interest, but I would like to restrict discussion to
only the architecture list.

The goal of this proposal is to twofold. First, it is a compatible
extension to the remote protocol to handle the problems of encryption
and (if desired) data compression. Second, it is a reformulation of the
remote implementation architecture to simplify and support future growth.

The overall picture is:

1. We define a new protocol type (PROTOCOL_VERSION11?) to support the
crypto and data compression extensions.
2. When the server starts up, it generates an RSA key pair for
session key exchange
3. The client includes PROTOCOL_VERSION11 in the list of protocols it
understands in the p_connect packet
4. When the server selects the crypto protocol, it follows the
existing p_accept packet with a link parameter block (lpb)
containing a list of potential encryption algorithms (None, DES,
DES3, AES128, AES196, AES256, etc), the server's public
encryption key, and a random number
5. The client selects an encryption algorithm from the server
supplied list and generates an appropriate session key.
6. The client prepends a link parameter block to the p_attach and
p_create (attach/create database) packets containing the selected
encryption algorithm and block encrypted with the server's public
key containing its session key and the server supplied random
number. If an encryption algorith other than None and a session
key is supplied, all bytes following the lpb and all subsequent
packets in either direction are encrypted with the session key.
7. A zero length link parameter block on p_accept, p_attach, or
p_create means that the encryption state of the connection is
unchanged.
8. Compression algorithms are handled in a manner parallel to
encryption algorithms.

A few notes:

1. The set of encryption algorithm supported on the server is
controlled by server configuration file. A server may be
configured to disallow unencrypted sessions.
2. The RSA key size can be controlled by server configuration file.
3. The scheme is forewards and backwards compatible with the existing
protocol negotiation. New clients can to talk old servers and old
client can talk to new servers, provided the server is configured
to allow unencrypted connections.
4. No additional message exchanges are required.
5. The client selects an encryption algorithm within policy
established by server, giving the client the option to tradeoff
security (key length) against performance.
6. The database name and database parameter block (containing account
and passwords) is encrypted with a session key
7. The server generated random number prevents replay attacks
8. The server private decrypt key exists nowhere other than server
process memory.
9. AES128 should probably be the default encryption algorithm for
both server and client.
10. The link parameter block (lpb) can be extended to support
differential encryption by packet type if desired.

While the wire protocol remains unchanged (except where extended for
PROTOCOL_VERSION11), the implementation departs from past practice in
that actual use of XDR is eliminated. Replacing XDR is a type hierarchy
with the following base class:

class Link
{
public:
virtual void putShort(short value);
virtual void putInt32(INT32 value);
virtual void putInt64(INT64 value);
virtual void putDouble(double value);
virtual void putCString(int length, const char* string);
virtual short getShort(void);
virtual INT32 getInt32(void);
virtual INT64 getInt64(void);
virtual double getDouble(void);

virtual void putBytes (int length, const UCHAR *bytes) = 0;
virtual void flushBlock(); // zero fills
current encryption block
virtual void flushMessage(); // flushes data
to network

virtual void getBytes (int length, UCHAR *bytes) = 0;
virtual void endBlock(); // ignore
remainder of encryption block
virtual int bytesAvailable() = 0; // bytes
available without network access
};

Transformation between network byte order and host byte order (the
endian problem) is performed by the base Link class.

A subclass will be created for each physical transport (LinkInet,
LinkXNet, LinkWNet, etc.), for each encryption family (LinkRSA, LinkDES,
LinkAES), a special in-memory utility class LinkEcho, and possibly one
or more compression classes. The classes are designed to be
transparently daisy chained so calls to be made direction to a physical
network object, an encryption object linked to a physical network
object, a compression object linked to a physical network object, or
even a compression object linked to an encrypt object linked to a
physical network object. The classes can also be used to perform
in-memory encryption/decryption such as:

LinkEcho echo;
LinkAES encrypt (128, key, &echo);
const char *message = "this is a character string";
encrypt.putCString (sizeof (message) - 1, message);
encrypt.flushMessage();
int encrypted length = echo.bytesAvailable();
UCHAR *encrypted = new [encryptedLength];
echo.getBytes(encryptedLength, encrypted);

Questions and comments are, as always, welcome.


[Non-text portions of this message have been removed]