/*************************************************
* Algorithms List Source File                    *
* (C) 1999-2003 The Botan Project                *
*************************************************/

#include <botan/lookup.h>
#include <botan/look_add.h>
#include <botan/look_pk.h>

#include <botan/aes.h>
#include <botan/des.h>

#include <botan/arc4.h>

#include <botan/sha160.h>
#include <botan/par_hash.h>

#include <botan/hmac.h>

#include <botan/mode_pad.h>

#include <botan/pkcs5.h>

namespace Botan {

/*************************************************
* Load the algorithms list                       *
*************************************************/
void load_algorithms_list()
   {
   add_algorithm(new AES);
   add_algorithm(new AES_128);
   add_algorithm(new AES_192);
   add_algorithm(new AES_256);
   add_algorithm(new DES);
   add_algorithm(new DESX);
   add_algorithm(new TripleDES);

   add_algorithm(new ARC4);

   add_algorithm(new SHA_160);

   add_algorithm(new PKCS7_Padding);
   add_algorithm(new OneAndZeros_Padding);
   add_algorithm(new ANSI_X923_Padding);
   add_algorithm(new Null_Padding);
   }

/*************************************************
* Some macros to simplify control flow           *
*************************************************/
#define HANDLE_TYPE_ONE_U32BIT(NAME, TYPE, DEFAULT) \
   if(algo_name == NAME)                            \
      {                                             \
      if(name.size() == 1)                          \
         return new TYPE(DEFAULT);                  \
      if(name.size() == 2)                          \
         return new TYPE(to_u32bit(name[1]));       \
      throw Invalid_Algorithm_Name(algo_spec);      \
      }

#define HANDLE_TYPE_TWO_U32BIT(NAME, TYPE, DEFAULT)               \
   if(algo_name == NAME)                                          \
      {                                                           \
      if(name.size() == 1)                                        \
         return new TYPE(DEFAULT);                                \
      if(name.size() == 2)                                        \
         return new TYPE(to_u32bit(name[1]));                     \
      if(name.size() == 3)                                        \
         return new TYPE(to_u32bit(name[1]), to_u32bit(name[2])); \
      throw Invalid_Algorithm_Name(algo_spec);                    \
      }

#define HANDLE_TYPE_ONE_STRING(NAME, TYPE)     \
   if(algo_name == NAME)                       \
      {                                        \
      if(name.size() == 2)                     \
         return new TYPE(name[1]);             \
      throw Invalid_Algorithm_Name(algo_spec); \
      }

/*************************************************
* Try to get a currently unloaded block cipher   *
*************************************************/
BlockCipher* try_to_get_bc(const std::string& algo_spec)
   {
   std::vector<std::string> name = parse_algorithm_name(algo_spec);
   if(name.size() == 0)
      return 0;

   return 0;
   }

/*************************************************
* Try to get a currently unloaded stream cipher  *
*************************************************/
StreamCipher* try_to_get_sc(const std::string& algo_spec)
   {
   std::vector<std::string> name = parse_algorithm_name(algo_spec);
   if(name.size() == 0)
      return 0;

   const std::string algo_name = deref_alias(name[0]);
   HANDLE_TYPE_ONE_U32BIT("RC4_drop", ARC4, 768);
   HANDLE_TYPE_ONE_U32BIT("MARK-4", ARC4, 256);
   return 0;
   }

/*************************************************
* Try to get a currently unloaded hash           *
*************************************************/
HashFunction* try_to_get_hash(const std::string& algo_spec)
   {
   std::vector<std::string> name = parse_algorithm_name(algo_spec);
   if(name.size() == 0)
      return 0;

   const std::string algo_name = deref_alias(name[0]);

   if(algo_name == "Parallel")
      {
      if(name.size() < 2)
         throw Invalid_Algorithm_Name(algo_spec);
      name.erase(name.begin());
      return new Parallel(name);
      }
   return 0;
   }

/*************************************************
* Try to get a currently unloaded MAC            *
*************************************************/
MessageAuthenticationCode* try_to_get_mac(const std::string& algo_spec)
   {
   std::vector<std::string> name = parse_algorithm_name(algo_spec);
   if(name.size() == 0)
      return 0;

   const std::string algo_name = deref_alias(name[0]);
   HANDLE_TYPE_ONE_STRING("HMAC", HMAC);
   return 0;
   }

/*************************************************
* Try to get a currently unloaded S2K            *
*************************************************/
S2K* try_to_get_s2k(const std::string& algo_spec)
   {
   std::vector<std::string> name = parse_algorithm_name(algo_spec);
   if(name.size() == 0)
      return 0;

   const std::string algo_name = deref_alias(name[0]);
   HANDLE_TYPE_ONE_STRING("PBKDF1", PKCS5_PBKDF1);
   HANDLE_TYPE_ONE_STRING("PBKDF2", PKCS5_PBKDF2);
   return 0;
   }

}
