/*************************************************
* Triple EDE Mode Header File                    *
* (C) 1999-2002 The OpenCL Project               *
*************************************************/

#ifndef OPENCL_TRIPLE_EDE_MODE_H__
#define OPENCL_TRIPLE_EDE_MODE_H__

#include <opencl/opencl.h>

namespace OpenCL {

/*************************************************
* Triple Key EDE Mode                            *
*************************************************/
template<typename B>
class Triple : public BlockCipher
   {
   public:
      static const u32bit BLOCKSIZE = B::BLOCKSIZE;

      void clear() throw() { C1.clear(); C2.clear(); C3.clear(); }
      std::string name() const { return "Triple<" + C1.name() + ">"; }
      BlockCipher* clone() const { return new Triple<B>; }
      Triple() : BlockCipher(name(), BLOCKSIZE, 3, 30, 3) {}
   private:
      void enc(const byte in[], byte out[]) const
         { C1.encrypt(in, out); C2.decrypt(out); C3.encrypt(out); }
      void dec(const byte in[], byte out[]) const
         { C3.decrypt(in, out); C2.encrypt(out); C1.decrypt(out); }
      void key(const byte[], u32bit);
      B C1, C2, C3;
   };

/*************************************************
* Triple Key EDE Mode Key Setup                  *
*************************************************/
template<typename B>
void Triple<B>::key(const byte key[], u32bit length)
   {
   if(!valid_keylength(length))
      throw Invalid_Key_Length(name(), length);
   C1.set_key(key                   , length / 3);
   C2.set_key(key +     (length / 3), length / 3);
   C3.set_key(key + 2 * (length / 3), length / 3);
   }

}

#endif
