/*************************************************
* Base Classes Header File                       *
* (C) 1999-2002 The OpenCL Project               *
*************************************************/

#ifndef OPENCL_BASE_H__
#define OPENCL_BASE_H__

#include <string>
#include <opencl/config.h>
#include <opencl/exceptn.h>
#include <opencl/symkey.h>

namespace OpenCL {

/*************************************************
* Algorithm Base Class                           *
*************************************************/
class Algorithm
   {
   public:
      virtual void clear() throw() = 0;
      virtual std::string name() const = 0;
      virtual ~Algorithm() {}
   };

/*************************************************
* Symmetric Algorithm Base Class                 *
*************************************************/
class SymmetricAlgorithm : public Algorithm
   {
   public:
      const u32bit MAXIMUM_KEYLENGTH, MINIMUM_KEYLENGTH, KEYLENGTH_MULTIPLE;
      void set_key(const SymmetricKey&) throw(Invalid_Key_Length);
      void set_key(const byte[], u32bit) throw(Invalid_Key_Length);
      bool valid_keylength(u32bit) const;
      SymmetricAlgorithm(u32bit, u32bit, u32bit);
      virtual ~SymmetricAlgorithm() {}
   private:
      virtual void key(const byte[], u32bit) = 0;
   };

/*************************************************
* Block Cipher Base Class                        *
*************************************************/
class BlockCipher : public SymmetricAlgorithm
   {
   public:
      const u32bit BLOCK_SIZE;
      void encrypt(const byte in[], byte out[]) const { enc(in, out); }
      void decrypt(const byte in[], byte out[]) const { dec(in, out); }
      void encrypt(byte block[]) const { enc(block, block); }
      void decrypt(byte block[]) const { dec(block, block); }
      virtual BlockCipher* clone() const = 0;
      BlockCipher(u32bit, u32bit, u32bit = 0, u32bit = 1);
      virtual ~BlockCipher() {}
   private:
      virtual void enc(const byte[], byte[]) const = 0;
      virtual void dec(const byte[], byte[]) const = 0;
   };

/*************************************************
* Stream Cipher Base Class                       *
*************************************************/
class StreamCipher : public SymmetricAlgorithm
   {
   public:
      void encrypt(const byte i[], byte o[], u32bit len) { cipher(i, o, len); }
      void decrypt(const byte i[], byte o[], u32bit len) { cipher(i, o, len); }
      void encrypt(byte in[], u32bit len) { cipher(in, in, len); }
      void decrypt(byte in[], u32bit len) { cipher(in, in, len); }
      virtual StreamCipher* clone() const = 0;
      StreamCipher(u32bit, u32bit = 0, u32bit = 1);
      virtual ~StreamCipher() {}
   private:
      virtual void cipher(const byte[], byte[], u32bit) = 0;
   };

/*************************************************
* Buffered Computation Base Class                *
*************************************************/
class BufferedComputation : public Algorithm
   {
   public:
      const u32bit OUTPUT_LENGTH;
      void update(const byte[], u32bit);
      void update(const std::string&);
      void final(byte out[]) { final_result(out); }
      SecureVector<byte> final();
      SecureVector<byte> process(const byte[], u32bit);
      SecureVector<byte> process(const std::string&);
      BufferedComputation(u32bit);
      virtual ~BufferedComputation() {}
   private:
      virtual void add_data(const byte[], u32bit) = 0;
      virtual void final_result(byte[]) = 0;
   };

/*************************************************
* Hash Function Base Class                       *
*************************************************/
class HashFunction : public BufferedComputation
   {
   public:
      const u32bit HASH_BLOCK_SIZE;
      virtual HashFunction* clone() const = 0;
      HashFunction(u32bit, u32bit = 0);
      virtual ~HashFunction() {}
   };

/*************************************************
* MessageAuthenticationCode Base Class           *
*************************************************/
class MessageAuthenticationCode : public BufferedComputation,
                                  public SymmetricAlgorithm
   {
   public:
      virtual std::string name() const = 0;
      virtual MessageAuthenticationCode* clone() const = 0;
      MessageAuthenticationCode(u32bit, u32bit, u32bit = 0, u32bit = 1);
      virtual ~MessageAuthenticationCode() {}
   };

/*************************************************
* Random Number Generator Base Class             *
*************************************************/
class RandomNumberGenerator : public Algorithm
   {
   public:
      virtual byte random() = 0;
      virtual void randomize(byte[], u32bit);
      void add_entropy(const byte[], u32bit);
      void add_entropy(class EntropySource&, bool = true);
      virtual ~RandomNumberGenerator() {}
   private:
      virtual void add_randomness(const byte[], u32bit) throw() = 0;
   };

/*************************************************
* Entropy Source Base Class                      *
*************************************************/
class EntropySource
   {
   public:
      virtual u32bit fast_poll(byte[], u32bit) = 0;
      virtual u32bit slow_poll(byte[], u32bit) = 0;
      virtual ~EntropySource() {}
   };

}

#endif
