// ---------------------------------------------------------------------------
// - Crypto.cpp                                                              -
// - afnix:sec module - cryptographic function implementation                -
// ---------------------------------------------------------------------------
// - This program is free software;  you can redistribute it  and/or  modify -
// - it provided that this copyright notice is kept intact.                  -
// -                                                                         -
// - This program  is  distributed in  the hope  that it will be useful, but -
// - without  any  warranty;  without  even   the   implied    warranty   of -
// - merchantability or fitness for a particular purpose.  In no event shall -
// - the copyright holder be liable for any  direct, indirect, incidental or -
// - special damages arising in any way out of the use of this software.     -
// ---------------------------------------------------------------------------
// - copyright (c) 1999-2011 amaury darsch                                   -
// ---------------------------------------------------------------------------

#include "Aes.hpp"
#include "Des.hpp"
#include "Rc2.hpp"
#include "Rc4.hpp"
#include "Rc5.hpp"
#include "Md2.hpp"
#include "Md4.hpp"
#include "Md5.hpp"
#include "Sha1.hpp"
#include "Sha224.hpp"
#include "Sha256.hpp"
#include "Sha384.hpp"
#include "Sha512.hpp"
#include "Crypto.hpp"

namespace afnix {
  
  // -------------------------------------------------------------------------
  // - hasher section                                                        -
  // -------------------------------------------------------------------------

  // create a new hasher by type

  Hasher* Crypto::mkhasher (const t_hasher type) {
    if (type == MD2)    return new Md2;
    if (type == MD4)    return new Md4;
    if (type == MD5)    return new Md5;
    if (type == SHA1)   return new Sha1;
    if (type == SHA224) return new Sha224;
    if (type == SHA256) return new Sha256;
    if (type == SHA384) return new Sha384;
    if (type == SHA512) return new Sha512;
    throw Exception ("hasher-error", "invalid hasher object type");
  }

  // create a new hasher by name

  Hasher* Crypto::mkhasher (const String& name) {
    if (name == "MD-2")    return new Md2;
    if (name == "MD-4")    return new Md4;
    if (name == "MD-5")    return new Md5;
    if (name == "SHA-1")   return new Sha1;
    if (name == "SHA-224") return new Sha224;
    if (name == "SHA-256") return new Sha256;
    if (name == "SHA-384") return new Sha384;
    if (name == "SHA-512") return new Sha512;
    throw Exception ("hasher-error", "invalid hasher object name", name);
  }

  // create a new hasher by size

  Hasher* Crypto::mkhasher (const long bits) {
    if (bits == 128) return new Md5;
    if (bits == 160) return new Sha1;
    if (bits == 224) return new Sha224;
    if (bits == 256) return new Sha256;
    if (bits == 384) return new Sha384;
    if (bits == 512) return new Sha512;
    throw Exception ("hasher-error", "invalid hasher size", (t_quad) bits);
  }

  // -------------------------------------------------------------------------
  // - cipher section                                                        -
  // -------------------------------------------------------------------------

  // create a new block cipher by type and key

  Cipher* Crypto::mkcipher (const t_cipher type, const Key& key) {
    if (type == AES) return new Aes (key);
    if (type == DES) return new Des (key);
    if (type == RC2) return new Rc2 (key);
    if (type == RC4) return new Rc4 (key);
    if (type == RC5) return new Rc5 (key);
    throw Exception ("cipher-error", "invalid cipher object type");
  }
  
  // create a new block cipher by name

  Cipher* Crypto::mkcipher (const String& name, const Key& key) { 
    if (name == "AES") return new Aes (key);
    if (name == "DES") return new Des (key);
    if (name == "RC2") return new Rc2 (key);
    if (name == "RC4") return new Rc4 (key);
    if (name == "RC5") return new Rc5 (key);
    throw Exception ("cipher-error", "invalid cipher object name", name);
  }
  
  // create a new block cipher by type and key

  Cipher* Crypto::mkcipher (const t_cipher type, const Key& key, 
			    const bool rflg) {
    if (type == AES) return new Aes (key, rflg);
    if (type == DES) return new Des (key, rflg);
    if (type == RC2) return new Rc2 (key, rflg);
    if (type == RC4) return new Rc4 (key, rflg);
    if (type == RC5) return new Rc5 (key, rflg);
    throw Exception ("cipher-error", "invalid cipher object type");
  }

  // create a new block cipher by name

  Cipher* Crypto::mkcipher (const String& name, const Key& key, 
			    const bool rflg) {
    if (name == "AES") return new Aes (key, rflg);
    if (name == "DES") return new Des (key, rflg);
    if (name == "RC2") return new Rc2 (key, rflg);
    if (name == "RC4") return new Rc4 (key, rflg);
    if (name == "RC5") return new Rc5 (key, rflg);
    throw Exception ("cipher-error", "invalid cipher object name", name);
  }
}
