text: /*
   * Copyright (c) 2001-2007, Tom St Denis
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
   *
   * 1. Redistributions of source code must retain the above copyright notice,
   * this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright notice,
   * this list of conditions and the following disclaimer in the documentation
   * and/or other materials provided with the distribution.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   * POSSIBILITY OF SUCH DAMAGE.
   */
  
  /* ---- SYMMETRIC KEY STUFF -----
   *
   * We put each of the ciphers scheduled keys in their own structs then we put all of 
   * the key formats in one union.  This makes the function prototypes easier to use.
   */
  
  #ifdef LTC_RIJNDAEL
  struct rijndael_key {
     ulong32 eK[60], dK[60];
     int Nr;
  };
  #endif
  
  
  #ifdef LTC_DES
  struct des_key {
      ulong32 ek[32], dk[32];
  };
  
  struct des3_key {
      ulong32 ek[3][32], dk[3][32];
  };
  #endif
  
  
  typedef union Symmetric_key {
  #ifdef LTC_DES
     struct des_key des;
     struct des3_key des3;
  #endif
  #ifdef LTC_RIJNDAEL
     struct rijndael_key rijndael;
  #endif
     void   *data;
  } symmetric_key;
  
  #ifdef LTC_ECB_MODE
  /** A block cipher ECB structure */
  typedef struct {
     /** The index of the cipher chosen */
     int                 cipher, 
     /** The block size of the given cipher */
                         blocklen;
     /** The scheduled key */                       
     symmetric_key       key;
  } symmetric_ECB;
  #endif
  
  #ifdef LTC_CFB_MODE
  /** A block cipher CFB structure */
  typedef struct {
     /** The index of the cipher chosen */
     int                 cipher, 
     /** The block size of the given cipher */                        
                         blocklen, 
     /** The padding offset */
                         padlen;
     /** The current IV */
     unsigned char       IV[MAXBLOCKSIZE], 
     /** The pad used to encrypt/decrypt */ 
                         pad[MAXBLOCKSIZE];
     /** The scheduled key */
     symmetric_key       key;
  } symmetric_CFB;
  #endif
  
  #ifdef LTC_OFB_MODE
  /** A block cipher OFB structure */
  typedef struct {
     /** The index of the cipher chosen */
     int                 cipher, 
     /** The block size of the given cipher */                        
                         blocklen, 
     /** The padding offset */
                         padlen;
     /** The current IV */
     unsigned char       IV[MAXBLOCKSIZE];
     /** The scheduled key */
     symmetric_key       key;
  } symmetric_OFB;
  #endif
  
  #ifdef LTC_CBC_MODE
  /** A block cipher CBC structure */
  typedef struct {
     /** The index of the cipher chosen */
     int                 cipher, 
     /** The block size of the given cipher */                        
                         blocklen;
     /** The current IV */
     unsigned char       IV[MAXBLOCKSIZE];
     /** The scheduled key */
     symmetric_key       key;
  } symmetric_CBC;
  #endif
  
  
  #ifdef LTC_CTR_MODE
  /** A block cipher CTR structure */
  typedef struct {
     /** The index of the cipher chosen */
     int                 cipher,
     /** The block size of the given cipher */                        
                         blocklen, 
     /** The padding offset */
                         padlen, 
     /** The mode (endianess) of the CTR, 0==little, 1==big */
                         mode,
     /** counter width */
                         ctrlen;
  
     /** The counter */                       
     unsigned char       ctr[MAXBLOCKSIZE], 
     /** The pad used to encrypt/decrypt */                       
                         pad[MAXBLOCKSIZE];
     /** The scheduled key */
     symmetric_key       key;
  } symmetric_CTR;
  #endif
  
  
  #ifdef LTC_LRW_MODE
  /** A LRW structure */
  typedef struct {
      /** The index of the cipher chosen (must be a 128-bit block cipher) */
      int               cipher;
  
      /** The current IV */
      unsigned char     IV[16],
   
      /** the tweak key */
                        tweak[16],
  
      /** The current pad, it's the product of the first 15 bytes against the tweak key */
                        pad[16];
  
      /** The scheduled symmetric key */
      symmetric_key     key;
  
  #ifdef LRW_TABLES
      /** The pre-computed multiplication table */
      unsigned char     PC[16][256][16];
  #endif
  } symmetric_LRW;
  #endif
  
  #ifdef LTC_F8_MODE
  /** A block cipher F8 structure */
  typedef struct {
     /** The index of the cipher chosen */
     int                 cipher, 
     /** The block size of the given cipher */                        
                         blocklen, 
     /** The padding offset */
                         padlen;
     /** The current IV */
     unsigned char       IV[MAXBLOCKSIZE],
                         MIV[MAXBLOCKSIZE];
     /** Current block count */
     ulong32             blockcnt;
     /** The scheduled key */
     symmetric_key       key;
  } symmetric_F8;
  #endif
  
  
  /** cipher descriptor table, last entry has "name == NULL" to mark the end of table */
  extern const struct ltc_cipher_descriptor {
     /** name of cipher */
     const char *name;
     /** internal ID */
     unsigned char ID;
     /** min keysize (octets) */
     int  min_key_length, 
     /** max keysize (octets) */
          max_key_length, 
     /** block size (octets) */
          block_length, 
     /** default number of rounds */
          default_rounds;
     /** Setup the cipher 
        @param key         The input symmetric key
        @param keylen      The length of the input key (octets)
        @param num_rounds  The requested number of rounds (0==default)
        @param skey        [out] The destination of the scheduled key
        @return CRYPT_OK if successful
     */
     int  (*setup)(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
     /** Encrypt a block
        @param pt      The plaintext
        @param ct      [out] The ciphertext
        @param skey    The scheduled key
        @return CRYPT_OK if successful
     */
     int (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
     /** Decrypt a block
        @param ct      The ciphertext
        @param pt      [out] The plaintext
        @param skey    The scheduled key
        @return CRYPT_OK if successful
     */
     int (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
     /** Test the block cipher
         @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
     */
     int (*test)(void);
  
     /** Terminate the context 
        @param skey    The scheduled key
     */
     void (*done)(symmetric_key *skey);      
  
     /** Determine a key size
         @param keysize    [in/out] The size of the key desired and the suggested size
         @return CRYPT_OK if successful
     */
     int  (*keysize)(int *keysize);
  
  /** Accelerators **/
     /** Accelerated ECB encryption 
         @param pt      Plaintext
         @param ct      Ciphertext
         @param blocks  The number of complete blocks to process
         @param skey    The scheduled key context
         @return CRYPT_OK if successful
     */
     int (*accel_ecb_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, symmetric_key *skey);
  
     /** Accelerated ECB decryption 
         @param pt      Plaintext
         @param ct      Ciphertext
         @param blocks  The number of complete blocks to process
         @param skey    The scheduled key context
         @return CRYPT_OK if successful
     */
     int (*accel_ecb_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, symmetric_key *skey);
  
     /** Accelerated CBC encryption 
         @param pt      Plaintext
         @param ct      Ciphertext
         @param blocks  The number of complete blocks to process
         @param IV      The initial value (input/output)
         @param skey    The scheduled key context
         @return CRYPT_OK if successful
     */
     int (*accel_cbc_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, symmetric_key *skey);
  
     /** Accelerated CBC decryption 
         @param pt      Plaintext
         @param ct      Ciphertext
         @param blocks  The number of complete blocks to process
         @param IV      The initial value (input/output)
         @param skey    The scheduled key context
         @return CRYPT_OK if successful
     */
     int (*accel_cbc_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, symmetric_key *skey);
  
     /** Accelerated CTR encryption 
         @param pt      Plaintext
         @param ct      Ciphertext
         @param blocks  The number of complete blocks to process
         @param IV      The initial value (input/output)
         @param mode    little or big endian counter (mode=0 or mode=1)
         @param skey    The scheduled key context
         @return CRYPT_OK if successful
     */
     int (*accel_ctr_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, int mode, symmetric_key *skey);
  
     /** Accelerated LRW 
         @param pt      Plaintext
         @param ct      Ciphertext
         @param blocks  The number of complete blocks to process
         @param IV      The initial value (input/output)
         @param tweak   The LRW tweak
         @param skey    The scheduled key context
         @return CRYPT_OK if successful
     */
     int (*accel_lrw_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey);
  
     /** Accelerated LRW 
         @param ct      Ciphertext
         @param pt      Plaintext
         @param blocks  The number of complete blocks to process
         @param IV      The initial value (input/output)
         @param tweak   The LRW tweak
         @param skey    The scheduled key context
         @return CRYPT_OK if successful
     */
     int (*accel_lrw_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey);
  
     /** Accelerated CCM packet (one-shot)
         @param key        The secret key to use
         @param keylen     The length of the secret key (octets)
         @param uskey      A previously scheduled key [optional can be NULL]
         @param nonce      The session nonce [use once]
         @param noncelen   The length of the nonce
         @param header     The header for the session
         @param headerlen  The length of the header (octets)
         @param pt         [out] The plaintext
         @param ptlen      The length of the plaintext (octets)
         @param ct         [out] The ciphertext
         @param tag        [out] The destination tag
         @param taglen     [in/out] The max size and resulting size of the authentication tag
         @param direction  Encrypt or Decrypt direction (0 or 1)
         @return CRYPT_OK if successful
     */
     int (*accel_ccm_memory)(
         const unsigned char *key,    unsigned long keylen,
         symmetric_key       *uskey,
         const unsigned char *nonce,  unsigned long noncelen,
         const unsigned char *header, unsigned long headerlen,
               unsigned char *pt,     unsigned long ptlen,
               unsigned char *ct,
               unsigned char *tag,    unsigned long *taglen,
                         int  direction);
  
     /** Accelerated GCM packet (one shot)
         @param key        The secret key
         @param keylen     The length of the secret key
         @param IV         The initial vector 
         @param IVlen      The length of the initial vector
         @param adata      The additional authentication data (header)
         @param adatalen   The length of the adata
         @param pt         The plaintext
         @param ptlen      The length of the plaintext (ciphertext length is the same)
         @param ct         The ciphertext
         @param tag        [out] The MAC tag
         @param taglen     [in/out] The MAC tag length
         @param direction  Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT)
         @return CRYPT_OK on success
     */
     int (*accel_gcm_memory)(
         const unsigned char *key,    unsigned long keylen,
         const unsigned char *IV,     unsigned long IVlen,
         const unsigned char *adata,  unsigned long adatalen,
               unsigned char *pt,     unsigned long ptlen,
               unsigned char *ct, 
               unsigned char *tag,    unsigned long *taglen,
                         int direction);
  
     /** Accelerated one shot LTC_OMAC 
         @param key            The secret key
         @param keylen         The key length (octets) 
         @param in             The message 
         @param inlen          Length of message (octets)
         @param out            [out] Destination for tag
         @param outlen         [in/out] Initial and final size of out
         @return CRYPT_OK on success
     */
     int (*omac_memory)(
         const unsigned char *key, unsigned long keylen,
         const unsigned char *in,  unsigned long inlen,
               unsigned char *out, unsigned long *outlen);
  
     /** Accelerated one shot XCBC 
         @param key            The secret key
         @param keylen         The key length (octets) 
         @param in             The message 
         @param inlen          Length of message (octets)
         @param out            [out] Destination for tag
         @param outlen         [in/out] Initial and final size of out
         @return CRYPT_OK on success
     */
     int (*xcbc_memory)(
         const unsigned char *key, unsigned long keylen,
         const unsigned char *in,  unsigned long inlen,
               unsigned char *out, unsigned long *outlen);
  
     /** Accelerated one shot F9 
         @param key            The secret key
         @param keylen         The key length (octets) 
         @param in             The message 
         @param inlen          Length of message (octets)
         @param out            [out] Destination for tag
         @param outlen         [in/out] Initial and final size of out
         @return CRYPT_OK on success
         @remark Requires manual padding
     */
     int (*f9_memory)(
         const unsigned char *key, unsigned long keylen,
         const unsigned char *in,  unsigned long inlen,
               unsigned char *out, unsigned long *outlen);
  
     /** Accelerated XTS encryption
         @param pt      Plaintext
         @param ct      Ciphertext
         @param blocks  The number of complete blocks to process
         @param tweak   The 128-bit encryption tweak (input/output).
                        The tweak should not be encrypted on input, but
                        next tweak will be copied encrypted on output.
         @param skey1   The first scheduled key context
         @param skey2   The second scheduled key context
         @return CRYPT_OK if successful
      */
      int (*accel_xts_encrypt)(const unsigned char *pt, unsigned char *ct,
          unsigned long blocks, unsigned char *tweak, symmetric_key *skey1,
          symmetric_key *skey2);
  
      /** Accelerated XTS decryption
          @param ct      Ciphertext
          @param pt      Plaintext
          @param blocks  The number of complete blocks to process
          @param tweak   The 128-bit encryption tweak (input/output).
                         The tweak should not be encrypted on input, but
                         next tweak will be copied encrypted on output.
          @param skey1   The first scheduled key context
          @param skey2   The second scheduled key context
          @return CRYPT_OK if successful
       */
       int (*accel_xts_decrypt)(const unsigned char *ct, unsigned char *pt,
           unsigned long blocks, unsigned char *tweak, symmetric_key *skey1,
           symmetric_key *skey2);
  } *cipher_descriptor[];
  
  
  /* make aes an alias */
  #define aes_setup           rijndael_setup
  #define aes_ecb_encrypt     rijndael_ecb_encrypt
  #define aes_ecb_decrypt     rijndael_ecb_decrypt
  #define aes_test            rijndael_test
  #define aes_done            rijndael_done
  #define aes_keysize         rijndael_keysize
  
  #define aes_enc_setup           rijndael_enc_setup
  #define aes_enc_ecb_encrypt     rijndael_enc_ecb_encrypt
  #define aes_enc_keysize         rijndael_enc_keysize
  
  int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
  int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
  int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
  int rijndael_test(void);
  void rijndael_done(symmetric_key *skey);
  int rijndael_keysize(int *keysize);
  int rijndael_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
  int rijndael_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
  void rijndael_enc_done(symmetric_key *skey);
  int rijndael_enc_keysize(int *keysize);
  extern const struct ltc_cipher_descriptor rijndael_desc, aes_desc;
  extern const struct ltc_cipher_descriptor rijndael_enc_desc, aes_enc_desc;
  
  
  
  
  int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
  int des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
  int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
  int des_test(void);
  void des_done(symmetric_key *skey);
  int des_keysize(int *keysize);
  int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
  int des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
  int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
  int des3_test(void);
  void des3_done(symmetric_key *skey);
  int des3_keysize(int *keysize);
  extern const struct ltc_cipher_descriptor des_desc, des3_desc;
  
  
  #ifdef LTC_ECB_MODE
  int ecb_start(int cipher, const unsigned char *key, 
                int keylen, int num_rounds, symmetric_ECB *ecb);
  int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb);
  int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb);
  int ecb_done(symmetric_ECB *ecb);
  #endif
  
  #ifdef LTC_CFB_MODE
  int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, 
                int keylen, int num_rounds, symmetric_CFB *cfb);
  int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb);
  int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb);
  int cfb_getiv(unsigned char *IV, unsigned long *len, symmetric_CFB *cfb);
  int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb);
  int cfb_done(symmetric_CFB *cfb);
  #endif
  
  #ifdef LTC_OFB_MODE
  int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, 
                int keylen, int num_rounds, symmetric_OFB *ofb);
  int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb);
  int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb);
  int ofb_getiv(unsigned char *IV, unsigned long *len, symmetric_OFB *ofb);
  int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb);
  int ofb_done(symmetric_OFB *ofb);
  #endif
  
  #ifdef LTC_CBC_MODE
  int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
                 int keylen, int num_rounds, symmetric_CBC *cbc);
  int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc);
  int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc);
  int cbc_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc);
  int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc);
  int cbc_done(symmetric_CBC *cbc);
  #endif
  
  #ifdef LTC_CTR_MODE
  
  #define CTR_COUNTER_LITTLE_ENDIAN    0x0000
  #define CTR_COUNTER_BIG_ENDIAN       0x1000
  #define LTC_CTR_RFC3686              0x2000
  
  int ctr_start(               int   cipher,
                const unsigned char *IV,
                const unsigned char *key,       int keylen,
                               int  num_rounds, int ctr_mode,
                     symmetric_CTR *ctr);
  int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr);
  int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr);
  int ctr_getiv(unsigned char *IV, unsigned long *len, symmetric_CTR *ctr);
  int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr);
  int ctr_done(symmetric_CTR *ctr);
  int ctr_test(void);
  #endif
  
  #ifdef LTC_LRW_MODE
  
  #define LRW_ENCRYPT 0
  #define LRW_DECRYPT 1
  
  int lrw_start(               int   cipher,
                const unsigned char *IV,
                const unsigned char *key,       int keylen,
                const unsigned char *tweak,
                               int  num_rounds, 
                     symmetric_LRW *lrw);
  int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw);
  int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw);
  int lrw_getiv(unsigned char *IV, unsigned long *len, symmetric_LRW *lrw);
  int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw);
  int lrw_done(symmetric_LRW *lrw);
  int lrw_test(void);
  
  /* don't call */
  int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw);
  #endif    
  
  #ifdef LTC_F8_MODE
  int f8_start(                int  cipher, const unsigned char *IV, 
               const unsigned char *key,                    int  keylen, 
               const unsigned char *salt_key,               int  skeylen,
                               int  num_rounds,   symmetric_F8  *f8);
  int f8_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_F8 *f8);
  int f8_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_F8 *f8);
  int f8_getiv(unsigned char *IV, unsigned long *len, symmetric_F8 *f8);
  int f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8);
  int f8_done(symmetric_F8 *f8);
  int f8_test_mode(void);
  #endif
  
  #ifdef LTC_XTS_MODE
  typedef struct {
     symmetric_key  key1, key2;
     int            cipher;
  } symmetric_xts;
  
  int xts_start(                int  cipher,
                const unsigned char *key1, 
                const unsigned char *key2, 
                      unsigned long  keylen,
                                int  num_rounds, 
                      symmetric_xts *xts);
  
  int xts_encrypt(
     const unsigned char *pt, unsigned long ptlen,
           unsigned char *ct,
  #ifdef LTC_LINARO_FIX_XTS
           unsigned char *tweak,
  #else
     const unsigned char *tweak,
  #endif
           symmetric_xts *xts);
  int xts_decrypt(
     const unsigned char *ct, unsigned long ptlen,
           unsigned char *pt,
  #ifdef LTC_LINARO_FIX_XTS
           unsigned char *tweak,
  #else
     const unsigned char *tweak,
  #endif
           symmetric_xts *xts);
  
  void xts_done(symmetric_xts *xts);
  int  xts_test(void);
  void xts_mult_x(unsigned char *I);
  #endif
  
  int find_cipher(const char *name);
  int find_cipher_any(const char *name, int blocklen, int keylen);
  int find_cipher_id(unsigned char ID);
  int register_cipher(const struct ltc_cipher_descriptor *cipher);
  int unregister_cipher(const struct ltc_cipher_descriptor *cipher);
  int cipher_is_valid(int idx);
  
  LTC_MUTEX_PROTO(ltc_cipher_mutex)
  
  /* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_cipher.h,v $ */
  /* $Revision: 1.54 $ */
  /* $Date: 2007/05/12 14:37:41 $ */
  