Table of Contents

Name

libmcrypt - encryption/decryption library

Synopsis

[see also mcrypt.h for more information]

Description

The libmcrypt is a data encryption library. The library is thread safe and provides encryption and decryption functions. This version of the library supports many encryption algorithms and encryption modes. Some algorithms which are supported: SERPENT, RIJNDAEL, 3DES, GOST, SAFER+, CAST-256, RC2, XTEA, 3WAY, TWOFISH, BLOWFISH, ARCFOUR, WAKE and more.

OFB, CBC, ECB, nOFB and CFB are the modes that all algorithms may function. ECB and CBC encrypt in blocks but CFB and OFB in bytes (8bits). Note that CFB and OFB in the rest of the document represent the "8bit CFB or OFB" mode. nOFB mode represents a n-bit OFB mode, n is used to represent the algorithm's block size. The library supports an extra STREAM mode to include some stream algorithms like WAKE or ARCFOUR.

In this version of the library all modes and algorithms are modular, which means that the algorithm and the mode is loaded at run-time. This way you can add algorithms and modes faster, and much easier.

A short description of the modes supported:

ECB: The Electronic CodeBook mode. It is the simplest mode to use with a block cipher. Encrypts each block independently.

CBC: The Cipher Block Chaining mode. It is better than ECB since the plaintext is XOR'ed with the previous ciphertext. A random block should be placed as the first block (IV) so the same block or messages always encrypt to something different.

CFB: The Cipher-Feedback Mode (in 8bit). This is a self-synchronizing stream cipher implemented from a block cipher.

OFB: The Output-Feedback Mode (in 8bit). This is a synchronous stream cipher implemented from a block cipher. It is intended for use in noisy lines, because corrupted ciphertext blocks do not corrupt the plaintext blocks that follow. Insecure (because used in 8bit mode) so it is recommended not to use it. Added just for completeness.

nOFB: The Output-Feedback Mode (in nbit). n Is the size of the block of the algorithm. This is a synchronous stream cipher implemented from a block cipher. It is intended for use in noisy lines, because corrupted ciphertext blocks do not corrupt the plaintext blocks that follow.

Error Recovery in these modes: If bytes are removed or lost from the file or stream in ECB, CBC and OFB modes, are impossible to recover, although CFB mode will recover. If some bytes are altered then a full block of plaintext is affected in ECB mode, two blocks in CBC and CFB modes, but only the corresponding byte in OFB mode.

Encryption can be done as follows:

A call to function: int mcrypt_module_open( char *algorithm, char* algorithm_directory, char* mode, char* mode_directory);

This function opens the module of the algorithm. The name of the algorithm is specified in algorithm, eg "twofish", and the algorithm_directory is the directory where the algorithm is (it may be null if it is the default). The same applies for the mode. The library is closed by calling mcrypt_module_close(), but there is no need to call that function if mcrypt_generic_end() is called. Normally it returns a thread descriptor (nothing to do with posix threads), or (-1) on error.

A call to function: int mcrypt_generic_init( int td, void *key, int lenofkey, void *IV);

This function initializes all buffers for the specified thread The maximum value of lenofkey should be the one obtained by calling mcrypt_get_key_size() and every value smaller than this is legal. Lenofkey should be specified in bytes not bits. The IV should normally have the size of the algorithms block size, but you must obtain the size by calling mcrypt_get_iv_size(). IV is ignored in ECB. IV MUST exist in CFB, CBC, STREAM, nOFB and OFB modes. It needs to be random and unique (but not secret). The same IV must be used for encryption/decryption. If you do not want to use it you should set it to zeros, but this is not recommended. It returns (-1) on error.

To encrypt now call:

int mcrypt_generic( int td, void *plaintext, int len);

This is the main encryption function. td is the thread descriptor returned by mcrypt_generic_init(). Plaintext is the plaintext you wish to encrypt and len should be the length (in bytes) of the plaintext and it should be k*algorithms_block_size if used in a mode which operated in blocks (cbc, ecb, nofb), or whatever when used in cfb or ofb which operate in streams. The plaintext is replaced by the ciphertext.

To decrypt you can call:

int mdecrypt_generic( int td, void *ciphertext, int len);

The decryption function. It is almost the same with mcrypt_generic.

When you're finished you should call:

int mcrypt_generic_end( const int td);

This function terminates encryption specified by the thread descriptor (td). Actually it clears all buffers, and closes all the modules used. Returns (-1) on error.

These are some extra functions:

void mcrypt_perror(int err);

This function prints a human readable description of the error 'err' in the stderr. The err should be a value returned by mcrypt_generic_init() or mcrypt_module_open().

int mcrypt_module_self_test (char* algorithm, char* libdir);

This function runs the self test on the specified algorithm. If the self test succeeds it returns zero. If the module is already opened you can call instead:

int mcrypt_self_test( int td);

which is almost the same.

is_block_algorithm_mode( int td); Returns 1 if the mode is for use with block algorithms, otherwise it returns 0. (eg. 0 for stream, and 1 for cbc, cfb, ofb)

is_block_algorithm( int td); Returns 1 if the algorithm is a block algorithm or 0 if it is a stream algorithm.

is_block_mode( int td); Returns 1 if the mode outputs blocks of bytes or 0 if it outputs bytes. (eg. 1 for cbc and ecb, and 0 for cfb and stream)

int mcrypt_get_block_size( int td);

Returns the block size of the algorithm specified by the thread descriptor in bytes. The algorithm MUST be opened using mcrypt_module_open().

int mcrypt_get_key_size( int td);

Returns the key size of the algorithm specified by the thread descriptor in bytes. The algorithm MUST be opened using mcrypt_module_open().

int mcrypt_get_supported_key_sizes( int td, int* sizes)

Returns the key sizes supported by the algorithm specified by the thread descriptor. If it returns zero and sizes is NULL then all key size between 1 and mcrypt_get_key_size() are supported by the algorithm. If it is 1 then only the mcrypt_get_key_size() size is supported and sizes[0] is equal to it. If it is greater than 1 then that number specifies the number of elements in sizes which are the key sizes that the algorithm supports. Sizes is malloc'ed so it should be free'ed.

int mcrypt_get_iv_size( int td);

Returns size of the IV of the algorithm specified by the thread descriptor in bytes. The algorithm MUST be opened using mcrypt_module_open(). If it is '0' then the IV is ignored in that algorithm. IV is used in CBC, CFB, OFB modes, and in some algorithms in STREAM mode.

char* mcrypt_get_algorithms_name( int td);

Returns a character array containing the name of the algorithm. This array is malloc'ed so it needs to be freed via free().

char* mcrypt_get_modes_name( int td);

Returns a character array containing the name of the mode. This array is malloc'ed so it needs to be freed via free().

char** mcrypt_list_algorithms ( char* libdir, int* size);

Returns a pointer to a character array cointaining all the mcrypt algorithms located in the libdir, or if it is NULL, in the default directory. The size is the number of the character arrays. You should remember to free the arrays since they are malloc'ed.

char** mcrypt_list_modes ( char* libdir, int *size);

Returns a pointer to a character array cointaining all the mcrypt modes located in the libdir, or if it is NULL, in the default directory. The size is the number of the character arrays. You should remember to free the arrays since they are malloc'ed.

void mcrypt_free_p (char **p, int size);

Frees the pointer to array returned by previous functions.

Some example programs follow here. Compile as "cc prog.c -lmcrypt -lltdl". Libltdl is used for opening dynamic libraries (modules).


/* First example: Encrypts stdin to stdout using TWOFISH with 128 bit key
and CFB */
#include <mcrypt.h>
#include <stdio.h>
#include <stdlib.h>
/* #include <mhash.h> */
main() {
  int td, i;
  char *key;
  char password[20];
  char block_buffer;
  char *IV;
  int keysize=16; /* 128 bits */
  key=calloc(1, keysize);
  strcpy(password, "A_large_key");
/* Generate the key using the password */
/*  mhash_keygen( KEYGEN_MCRYPT, MHASH_MD5, key, keysize, NULL, 0, password,
strlen(password));
 */
  memmove( key, password, strlen(password));
  td = mcrypt_module_open("twofish", NULL, "cfb", NULL);
  if (td<0) {
     mcrypt_perror(td);
     return 1;
  }
  IV = malloc(mcrypt_get_iv_size(td));
/* Put random data in IV. Note these are not real random data, 
 * consider using /dev/random or /dev/urandom.
 */
  /*  srand(time(0)); */
  for (i=0; i< mcrypt_get_iv_size( td); i++) {
    IV[i]=rand();
  }
  i=mcrypt_generic_init( td, key, keysize, IV);
  if (i<0) {
     mcrypt_perror(i);
     return 1;
  }
  /* Encryption in CFB is performed in bytes */
  while ( fread (&block_buffer, 1, 1, stdin) == 1 ) {
      mcrypt_generic (td, &block_buffer, 1);
/* Comment above and uncomment this to decrypt */
/*    mdecrypt_generic (td, &block_buffer, 1);  */
      fwrite ( &block_buffer, 1, 1, stdout);
  }
  mcrypt_generic_end(td);
  return 0;
}
/* Second Example: encrypts using CBC and SAFER+ with 192 bits key */
#include <mcrypt.h>
#include <stdio.h>
#include <stdlib.h>
main() {
  int td, i;
  char *key; /* created using mcrypt_gen_key */
  char *block_buffer;
  char *IV;
  int blocksize;
  int keysize = 24; /* 192 bits == 24 bytes */
  key = calloc(1, keysize);
  strcpy(key, "A_large_and_random_key"); 
  td = mcrypt_module_open("saferplus", NULL, "cbc", NULL);
  blocksize = mcrypt_get_block_size(td);
  block_buffer = malloc(blocksize);
/* but unfortunately this does not fill all the key so the rest bytes are
 * padded with zeros. Try to use large keys or convert them with mcrypt_gen_key().
 */
  IV=malloc(mcrypt_get_iv_size(td));
/* Put random data in IV. Note these are not real random data, 
 * consider using /dev/random or /dev/urandom.
 */
/* srand(time(0)); */
  for (i=0; i < mcrypt_get_iv_size(td); i++) {
    IV[i]=rand();
  }
  mcrypt_generic_init ( td key, keysize, IV);
  /* Encryption in CBC is performed in blocks */
  while ( fread (block_buffer, 1, blocksize, stdin) == blocksize ) {
      mcrypt_generic (td, block_buffer, blocksize);
/*      mdecrypt_generic (td, block_buffer, blocksize); */
      fwrite ( block_buffer, 1, blocksize, stdout);
  }
  mcrypt_generic_end (td);
  return 0;
}

The library does not install any signal handler.

Questions about libmcrypt should be sent to:

mcrypt-dev@argeas.cs-net.gr
or, if this fails, to the author addresses given below. The mcrypt home page is:
http://hq.hellug.gr/~mcrypt

Authors

Version 2.3 Copyright (C) 1998-1999 Nikos Mavroyanopoulos (nmav@hellug.gr).

Thanks to all the people who reported problems and suggested various improvements for mcrypt; who are too numerous to cite here.


DES: IBM & NSA
CAST: Carlisle Adams & Stafford Tavares
xTEA: David Wheeler & Roger M. Needham
3-WAY: Joan Daemen
Blowfish: Bruce Schneier
Twofish: Bruce Schneier, Doug Whiting, John Kelsey, Chris Hall, David Wagner
GOST: A.Zabotin, G.P. Glazkov, and V.B. Isaeva
SAFER: J.L. Massey
RC2/RC4/RC6: Ron Rivest
IDEA: J.L. Massey, Xuejia Lai
RIJNDAEL: Joan Daemen and Vincent Rijmen
SEPENT: Ross Anderson, Eli Biham and Lars Knudsen


Table of Contents