Botan  1.11.15
src/lib/block/noekeon/noekeon.cpp
Go to the documentation of this file.
00001 /*
00002 * Noekeon
00003 * (C) 1999-2008 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #include <botan/internal/block_utils.h>
00009 #include <botan/noekeon.h>
00010 
00011 namespace Botan {
00012 
00013 BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(Noekeon);
00014 
00015 namespace {
00016 
00017 /*
00018 * Noekeon's Theta Operation
00019 */
00020 inline void theta(u32bit& A0, u32bit& A1,
00021                   u32bit& A2, u32bit& A3,
00022                   const u32bit EK[4])
00023    {
00024    u32bit T = A0 ^ A2;
00025    T ^= rotate_left(T, 8) ^ rotate_right(T, 8);
00026    A1 ^= T;
00027    A3 ^= T;
00028 
00029    A0 ^= EK[0];
00030    A1 ^= EK[1];
00031    A2 ^= EK[2];
00032    A3 ^= EK[3];
00033 
00034    T = A1 ^ A3;
00035    T ^= rotate_left(T, 8) ^ rotate_right(T, 8);
00036    A0 ^= T;
00037    A2 ^= T;
00038    }
00039 
00040 /*
00041 * Theta With Null Key
00042 */
00043 inline void theta(u32bit& A0, u32bit& A1,
00044                   u32bit& A2, u32bit& A3)
00045    {
00046    u32bit T = A0 ^ A2;
00047    T ^= rotate_left(T, 8) ^ rotate_right(T, 8);
00048    A1 ^= T;
00049    A3 ^= T;
00050 
00051    T = A1 ^ A3;
00052    T ^= rotate_left(T, 8) ^ rotate_right(T, 8);
00053    A0 ^= T;
00054    A2 ^= T;
00055    }
00056 
00057 /*
00058 * Noekeon's Gamma S-Box Layer
00059 */
00060 inline void gamma(u32bit& A0, u32bit& A1, u32bit& A2, u32bit& A3)
00061    {
00062    A1 ^= ~A3 & ~A2;
00063    A0 ^= A2 & A1;
00064 
00065    u32bit T = A3;
00066    A3 = A0;
00067    A0 = T;
00068 
00069    A2 ^= A0 ^ A1 ^ A3;
00070 
00071    A1 ^= ~A3 & ~A2;
00072    A0 ^= A2 & A1;
00073    }
00074 
00075 }
00076 
00077 /*
00078 * Noekeon Round Constants
00079 */
00080 const byte Noekeon::RC[] = {
00081    0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A,
00082    0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A,
00083    0xD4 };
00084 
00085 /*
00086 * Noekeon Encryption
00087 */
00088 void Noekeon::encrypt_n(const byte in[], byte out[], size_t blocks) const
00089    {
00090    for(size_t i = 0; i != blocks; ++i)
00091       {
00092       u32bit A0 = load_be<u32bit>(in, 0);
00093       u32bit A1 = load_be<u32bit>(in, 1);
00094       u32bit A2 = load_be<u32bit>(in, 2);
00095       u32bit A3 = load_be<u32bit>(in, 3);
00096 
00097       for(size_t j = 0; j != 16; ++j)
00098          {
00099          A0 ^= RC[j];
00100          theta(A0, A1, A2, A3, &EK[0]);
00101 
00102          A1 = rotate_left(A1, 1);
00103          A2 = rotate_left(A2, 5);
00104          A3 = rotate_left(A3, 2);
00105 
00106          gamma(A0, A1, A2, A3);
00107 
00108          A1 = rotate_right(A1, 1);
00109          A2 = rotate_right(A2, 5);
00110          A3 = rotate_right(A3, 2);
00111          }
00112 
00113       A0 ^= RC[16];
00114       theta(A0, A1, A2, A3, &EK[0]);
00115 
00116       store_be(out, A0, A1, A2, A3);
00117 
00118       in += BLOCK_SIZE;
00119       out += BLOCK_SIZE;
00120       }
00121    }
00122 
00123 /*
00124 * Noekeon Encryption
00125 */
00126 void Noekeon::decrypt_n(const byte in[], byte out[], size_t blocks) const
00127    {
00128    for(size_t i = 0; i != blocks; ++i)
00129       {
00130       u32bit A0 = load_be<u32bit>(in, 0);
00131       u32bit A1 = load_be<u32bit>(in, 1);
00132       u32bit A2 = load_be<u32bit>(in, 2);
00133       u32bit A3 = load_be<u32bit>(in, 3);
00134 
00135       for(size_t j = 16; j != 0; --j)
00136          {
00137          theta(A0, A1, A2, A3, &DK[0]);
00138          A0 ^= RC[j];
00139 
00140          A1 = rotate_left(A1, 1);
00141          A2 = rotate_left(A2, 5);
00142          A3 = rotate_left(A3, 2);
00143 
00144          gamma(A0, A1, A2, A3);
00145 
00146          A1 = rotate_right(A1, 1);
00147          A2 = rotate_right(A2, 5);
00148          A3 = rotate_right(A3, 2);
00149          }
00150 
00151       theta(A0, A1, A2, A3, &DK[0]);
00152       A0 ^= RC[0];
00153 
00154       store_be(out, A0, A1, A2, A3);
00155 
00156       in += BLOCK_SIZE;
00157       out += BLOCK_SIZE;
00158       }
00159    }
00160 
00161 /*
00162 * Noekeon Key Schedule
00163 */
00164 void Noekeon::key_schedule(const byte key[], size_t)
00165    {
00166    u32bit A0 = load_be<u32bit>(key, 0);
00167    u32bit A1 = load_be<u32bit>(key, 1);
00168    u32bit A2 = load_be<u32bit>(key, 2);
00169    u32bit A3 = load_be<u32bit>(key, 3);
00170 
00171    for(size_t i = 0; i != 16; ++i)
00172       {
00173       A0 ^= RC[i];
00174       theta(A0, A1, A2, A3);
00175 
00176       A1 = rotate_left(A1, 1);
00177       A2 = rotate_left(A2, 5);
00178       A3 = rotate_left(A3, 2);
00179 
00180       gamma(A0, A1, A2, A3);
00181 
00182       A1 = rotate_right(A1, 1);
00183       A2 = rotate_right(A2, 5);
00184       A3 = rotate_right(A3, 2);
00185       }
00186 
00187    A0 ^= RC[16];
00188 
00189    DK.resize(4);
00190    DK[0] = A0;
00191    DK[1] = A1;
00192    DK[2] = A2;
00193    DK[3] = A3;
00194 
00195    theta(A0, A1, A2, A3);
00196 
00197    EK.resize(4);
00198    EK[0] = A0;
00199    EK[1] = A1;
00200    EK[2] = A2;
00201    EK[3] = A3;
00202    }
00203 
00204 /*
00205 * Clear memory of sensitive data
00206 */
00207 void Noekeon::clear()
00208    {
00209    zap(EK);
00210    zap(DK);
00211    }
00212 
00213 }