               Diamond Cryptosystem DLL by Andy Brown 1994
               -------------------------------------------

Description
-----------
Diamond is a cipher designed to exceed DES in strength. Diamond uses a
variable length key of at least 40 bits. The use of at least a 128 bit key
is recommended for long term protection of very sensitive data, as a hedge
against the possibility of computing power increasing by several orders of
magnitudes in the coming years. At least 10 rounds, preferably 15, should
be used with the full Diamond algorithm.

Where software speed and table space are critical, a variant of Diamond
called Diamond Lite that has a block size of 8 bytes (64 bits) and a
minimum of four rounds (8 recommended) is a reasonable compromise. This
variant has the advantage that every bit of the output is a function of
every bit of the input and every bit of the key after only two rounds. At
least four rounds are needed, however, to ensure that the algorithm is
strong enough to justify keys of about 64 bits. This only requires 8192
bytes of table space and offers faster speed in software than the full
Diamond with a 16 bit block size.

It is conjectured that Diamond Lite with 8 rounds and a key length of 128
bits is at least equivalent in security to the IDEA cipher, and more secure
than the ageing DES algorithm.


Using DIAMOND.DLL
-----------------
For Borland C++ IDE projects, add DIAMOND.LIB to your project. Makefile
based projects need to add DIAMOND.LIB to the linker stage.

Include DIAMOND.H in any of your project files that need to call the
Diamond/Diamond Lite encryption routines.

Ensure DIAMOND.DLL is either in somewhere in your PATH environment
variable, or in your Windows SYSTEM directory.

The file `DIAMOND.DAT' contains a list of plaintext/key/ciphertext values
that you can use to make sure that your Diamond code is functioning
correctly.


                                   API
                                   ---

UINT FAR PASCAL set_diamond_key(LPBYTE external_key,WORD key_size,
                                WORD rounds,BOOL invert,
                                LPDIAMONDKEY dmkey,
                                UINT type)

external_key  FAR pointer to a BYTE buffer holding the cipher key
key_size      The size, in bytes, of the external_key parameter
rounds        The number of rounds that the cipher is to perform. See the
              above description for recommended values for this parameter.
invert        TRUE for encryption/decryption, FALSE for encryption only.
              Always setting this to TRUE is a safe thing to do.
dmkey         A FAR pointer to a DIAMONDKEY structure that this function
              will fill in for you. This structure contains internal
              information that the encryption/decryption functions need.
type          Either DIAMOND_FULL or DIAMOND_LITE, depending on the cipher
              that you want to use.

Return value  zero for success, otherwise one of the following:

              DERR_ROUNDS
                  An invalid number of rounds was selected
              DERR_MEMORY
                  Memory allocation failed (pretty unlikely)

              You need to call this function before you attempt to use any
              of the encryption/decryption functions.


VOID FAR PASCAL diamond_encrypt_block(LPBYTE x,LPBYTE y,LPDIAMONDKEY dmkey)

x      FAR pointer to plaintext to encrypt
y      FAR pointer to buffer to hold ciphertext
dmkey  A FAR pointer to the DIAMONDKEY structure filled in by the
       set_diamond_key() function

       Encrypts one 16 byte block using the full Diamond algorithm. `y' must
       be at least 16 bytes in size.


VOID FAR PASCAL diamond_decrypt_block(LPBYTE x,LPBYTE y,LPDIAMONDKEY dmkey)

x      FAR pointer to ciphertext to decrypt
y      FAR pointer to buffer to hold decrypted plaintext
dmkey  A FAR pointer to the DIAMONDKEY structure filled in by the
       set_diamond_key() function

       Decrypts one 16 byte block of ciphertext using the full Diamond
       algorithm. `y' must be at least 16 bytes in size.


VOID FAR PASCAL lite_encrypt_block(LPBYTE x,LPBYTE y,LPDIAMONDKEY dmkey)

x      FAR pointer to plaintext to encrypt
y      FAR pointer to buffer to hold encrypted plaintext
dmkey  A FAR pointer to the DIAMONDKEY structure filled in by the
       set_diamond_key() function

      Encrypts one 8 byte block of ciphertext using the Diamond Lite
      algorithm. `y' must be at least 16 bytes in size.


VOID FAR PASCAL lite_decrypt_block(LPBYTE x,LPBYTE y,LPDIAMONDKEY dmkey)

x      FAR pointer to ciphertext to decrypt
y      FAR pointer to buffer to hold decrypted plaintext
dmkey  A FAR pointer to the DIAMONDKEY structure filled in by the
       set_diamond_key() function

       Decrypts one 8 byte block of ciphertext using the Diamond Lite
       algorithm. `y' must be at least 16 bytes in size.


VOID FAR PASCAL diamond_done(LPDIAMONDKEY dmkey)

dmkey  A FAR pointer to the DIAMONDKEY structure filled in by the
       set_diamond_key function

       Frees memory allocated by the set_diamond_key() function and zeros the
       internal s-boxes. This function is a complement to the
       set_diamond_key() function.


Example
-------
To encrypt a 16 byte block using the Diamond algorithm with 15 rounds, you
may have a program fragment like this:

void encrypt_block(BYTE *plaintext,BYTE *ciphertext,BYTE *key,WORD keysize)
{
DIAMONDKEY dmkey;

  set_diamond_key(key,keysize,15,FALSE,&dmkey,DIAMOND_FULL);
  diamond_encrypt_block(plaintext,ciphertext,dmkey);
  diamond_done(dmkey);
}

To decrypt a 16 byte block using the Diamond algorithm with 15 rounds, you
may have a program fragment like this:

void decrypt_block(BYTE *plaintext,BYTE *ciphertext,BYTE *key,WORD keysize)
{                             
DIAMONDKEY dmkey;

  set_diamond_key(key,keysize,15,TRUE,&dmkey,DIAMOND_FULL);
  diamond_decrypt_block(ciphertext,plaintext,dmkey);
  diamond_done(dmkey);
}

Of course in your application you will be calling set_diamond_key() once
before encrypting multiple blocks and then calling diamond_done()
afterwards.


Comments
--------
The DLL was compiled with Borland C++ v3.1 with optimizations set to
`fastest', using the 286 instruction set option. You can probably get quite
a speed increase using the 386 instruction set.


Have fun,

Andy

+---------------------------+----------------------------------------------+
| Andy <asb@cs.nott.ac.uk>  | PGP key fingerprint: EC 80 9C 96 54 63 CC 97 |
|    finger for PGP key     |                    : FF 7D C5 69 0B 55 23 63 |
+---------------------------+----------------------------------------------+
