Botan  1.11.15
src/lib/block/threefish/threefish.cpp
Go to the documentation of this file.
00001 /*
00002 * Threefish-512
00003 * (C) 2013,2014 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/threefish.h>
00010 
00011 namespace Botan {
00012 
00013 BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(Threefish_512, "Threefish-512");
00014 
00015 #define THREEFISH_ROUND(X0,X1,X2,X3,X4,X5,X6,X7,ROT1,ROT2,ROT3,ROT4) \
00016    do {                                                              \
00017       X0 += X4;                                                      \
00018       X1 += X5;                                                      \
00019       X2 += X6;                                                      \
00020       X3 += X7;                                                      \
00021       X4 = rotate_left(X4, ROT1);                                    \
00022       X5 = rotate_left(X5, ROT2);                                    \
00023       X6 = rotate_left(X6, ROT3);                                    \
00024       X7 = rotate_left(X7, ROT4);                                    \
00025       X4 ^= X0;                                                      \
00026       X5 ^= X1;                                                      \
00027       X6 ^= X2;                                                      \
00028       X7 ^= X3;                                                      \
00029    } while(0)
00030 
00031 #define THREEFISH_INJECT_KEY(r)              \
00032    do {                                      \
00033       X0 += m_K[(r  ) % 9];                  \
00034       X1 += m_K[(r+1) % 9];                  \
00035       X2 += m_K[(r+2) % 9];                  \
00036       X3 += m_K[(r+3) % 9];                  \
00037       X4 += m_K[(r+4) % 9];                  \
00038       X5 += m_K[(r+5) % 9] + m_T[(r  ) % 3]; \
00039       X6 += m_K[(r+6) % 9] + m_T[(r+1) % 3]; \
00040       X7 += m_K[(r+7) % 9] + (r);            \
00041    } while(0)
00042 
00043 #define THREEFISH_ENC_8_ROUNDS(R1,R2)                         \
00044    do {                                                       \
00045       THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 46,36,19,37); \
00046       THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 33,27,14,42); \
00047       THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 17,49,36,39); \
00048       THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 44, 9,54,56); \
00049       THREEFISH_INJECT_KEY(R1);                               \
00050                                                               \
00051       THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 39,30,34,24); \
00052       THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 13,50,10,17); \
00053       THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 25,29,39,43); \
00054       THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3,  8,35,56,22); \
00055       THREEFISH_INJECT_KEY(R2);                               \
00056    } while(0)
00057 
00058 void Threefish_512::skein_feedfwd(const secure_vector<u64bit>& M,
00059                                   const secure_vector<u64bit>& T)
00060    {
00061    BOTAN_ASSERT(m_K.size() == 9, "Key was set");
00062    BOTAN_ASSERT(M.size() == 8, "Single block");
00063 
00064    m_T[0] = T[0];
00065    m_T[1] = T[1];
00066    m_T[2] = T[0] ^ T[1];
00067 
00068    u64bit X0 = M[0];
00069    u64bit X1 = M[1];
00070    u64bit X2 = M[2];
00071    u64bit X3 = M[3];
00072    u64bit X4 = M[4];
00073    u64bit X5 = M[5];
00074    u64bit X6 = M[6];
00075    u64bit X7 = M[7];
00076 
00077    THREEFISH_INJECT_KEY(0);
00078 
00079    THREEFISH_ENC_8_ROUNDS(1,2);
00080    THREEFISH_ENC_8_ROUNDS(3,4);
00081    THREEFISH_ENC_8_ROUNDS(5,6);
00082    THREEFISH_ENC_8_ROUNDS(7,8);
00083    THREEFISH_ENC_8_ROUNDS(9,10);
00084    THREEFISH_ENC_8_ROUNDS(11,12);
00085    THREEFISH_ENC_8_ROUNDS(13,14);
00086    THREEFISH_ENC_8_ROUNDS(15,16);
00087    THREEFISH_ENC_8_ROUNDS(17,18);
00088 
00089    m_K[0] = M[0] ^ X0;
00090    m_K[1] = M[1] ^ X1;
00091    m_K[2] = M[2] ^ X2;
00092    m_K[3] = M[3] ^ X3;
00093    m_K[4] = M[4] ^ X4;
00094    m_K[5] = M[5] ^ X5;
00095    m_K[6] = M[6] ^ X6;
00096    m_K[7] = M[7] ^ X7;
00097 
00098    m_K[8] = m_K[0] ^ m_K[1] ^ m_K[2] ^ m_K[3] ^
00099             m_K[4] ^ m_K[5] ^ m_K[6] ^ m_K[7] ^ 0x1BD11BDAA9FC1A22;
00100    }
00101 
00102 void Threefish_512::encrypt_n(const byte in[], byte out[], size_t blocks) const
00103    {
00104    BOTAN_ASSERT(m_K.size() == 9, "Key was set");
00105    BOTAN_ASSERT(m_T.size() == 3, "Tweak was set");
00106 
00107    for(size_t i = 0; i != blocks; ++i)
00108       {
00109       u64bit X0 = load_le<u64bit>(in, 0);
00110       u64bit X1 = load_le<u64bit>(in, 1);
00111       u64bit X2 = load_le<u64bit>(in, 2);
00112       u64bit X3 = load_le<u64bit>(in, 3);
00113       u64bit X4 = load_le<u64bit>(in, 4);
00114       u64bit X5 = load_le<u64bit>(in, 5);
00115       u64bit X6 = load_le<u64bit>(in, 6);
00116       u64bit X7 = load_le<u64bit>(in, 7);
00117 
00118       THREEFISH_INJECT_KEY(0);
00119 
00120       THREEFISH_ENC_8_ROUNDS(1,2);
00121       THREEFISH_ENC_8_ROUNDS(3,4);
00122       THREEFISH_ENC_8_ROUNDS(5,6);
00123       THREEFISH_ENC_8_ROUNDS(7,8);
00124       THREEFISH_ENC_8_ROUNDS(9,10);
00125       THREEFISH_ENC_8_ROUNDS(11,12);
00126       THREEFISH_ENC_8_ROUNDS(13,14);
00127       THREEFISH_ENC_8_ROUNDS(15,16);
00128       THREEFISH_ENC_8_ROUNDS(17,18);
00129 
00130       store_le(out, X0, X1, X2, X3, X4, X5, X6, X7);
00131 
00132       in += 64;
00133       out += 64;
00134       }
00135    }
00136 
00137 #undef THREEFISH_ENC_8_ROUNDS
00138 #undef THREEFISH_INJECT_KEY
00139 #undef THREEFISH_ROUND
00140 
00141 void Threefish_512::decrypt_n(const byte in[], byte out[], size_t blocks) const
00142    {
00143    BOTAN_ASSERT(m_K.size() == 9, "Key was set");
00144    BOTAN_ASSERT(m_T.size() == 3, "Tweak was set");
00145 
00146 #define THREEFISH_ROUND(X0,X1,X2,X3,X4,X5,X6,X7,ROT1,ROT2,ROT3,ROT4) \
00147    do {                                                              \
00148       X4 ^= X0;                                                      \
00149       X5 ^= X1;                                                      \
00150       X6 ^= X2;                                                      \
00151       X7 ^= X3;                                                      \
00152       X4 = rotate_right(X4, ROT1);                                   \
00153       X5 = rotate_right(X5, ROT2);                                   \
00154       X6 = rotate_right(X6, ROT3);                                   \
00155       X7 = rotate_right(X7, ROT4);                                   \
00156       X0 -= X4;                                                      \
00157       X1 -= X5;                                                      \
00158       X2 -= X6;                                                      \
00159       X3 -= X7;                                                      \
00160    } while(0)
00161 
00162 #define THREEFISH_INJECT_KEY(r)              \
00163    do {                                      \
00164       X0 -= m_K[(r  ) % 9];                  \
00165       X1 -= m_K[(r+1) % 9];                  \
00166       X2 -= m_K[(r+2) % 9];                  \
00167       X3 -= m_K[(r+3) % 9];                  \
00168       X4 -= m_K[(r+4) % 9];                  \
00169       X5 -= m_K[(r+5) % 9] + m_T[(r  ) % 3]; \
00170       X6 -= m_K[(r+6) % 9] + m_T[(r+1) % 3]; \
00171       X7 -= m_K[(r+7) % 9] + (r);            \
00172    } while(0)
00173 
00174 #define THREEFISH_DEC_8_ROUNDS(R1,R2)                         \
00175    do {                                                       \
00176       THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3,  8,35,56,22); \
00177       THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 25,29,39,43); \
00178       THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 13,50,10,17); \
00179       THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 39,30,34,24); \
00180       THREEFISH_INJECT_KEY(R1);                               \
00181                                                               \
00182       THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 44, 9,54,56); \
00183       THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 17,49,36,39); \
00184       THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 33,27,14,42); \
00185       THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 46,36,19,37); \
00186       THREEFISH_INJECT_KEY(R2);                               \
00187    } while(0)
00188 
00189    for(size_t i = 0; i != blocks; ++i)
00190       {
00191       u64bit X0 = load_le<u64bit>(in, 0);
00192       u64bit X1 = load_le<u64bit>(in, 1);
00193       u64bit X2 = load_le<u64bit>(in, 2);
00194       u64bit X3 = load_le<u64bit>(in, 3);
00195       u64bit X4 = load_le<u64bit>(in, 4);
00196       u64bit X5 = load_le<u64bit>(in, 5);
00197       u64bit X6 = load_le<u64bit>(in, 6);
00198       u64bit X7 = load_le<u64bit>(in, 7);
00199 
00200       THREEFISH_INJECT_KEY(18);
00201 
00202       THREEFISH_DEC_8_ROUNDS(17,16);
00203       THREEFISH_DEC_8_ROUNDS(15,14);
00204       THREEFISH_DEC_8_ROUNDS(13,12);
00205       THREEFISH_DEC_8_ROUNDS(11,10);
00206       THREEFISH_DEC_8_ROUNDS(9,8);
00207       THREEFISH_DEC_8_ROUNDS(7,6);
00208       THREEFISH_DEC_8_ROUNDS(5,4);
00209       THREEFISH_DEC_8_ROUNDS(3,2);
00210       THREEFISH_DEC_8_ROUNDS(1,0);
00211 
00212       store_le(out, X0, X1, X2, X3, X4, X5, X6, X7);
00213 
00214       in += 64;
00215       out += 64;
00216       }
00217 
00218 #undef THREEFISH_DEC_8_ROUNDS
00219 #undef THREEFISH_INJECT_KEY
00220 #undef THREEFISH_ROUND
00221    }
00222 
00223 void Threefish_512::set_tweak(const byte tweak[], size_t len)
00224    {
00225    if(len != 16)
00226       throw std::runtime_error("Unsupported twofish tweak length");
00227    m_T.resize(3);
00228    m_T[0] = load_le<u64bit>(tweak, 0);
00229    m_T[1] = load_le<u64bit>(tweak, 1);
00230    m_T[2] = m_T[0] ^ m_T[1];
00231    }
00232 
00233 void Threefish_512::key_schedule(const byte key[], size_t)
00234    {
00235    // todo: define key schedule for smaller keys
00236    m_K.resize(9);
00237 
00238    for(size_t i = 0; i != 8; ++i)
00239       m_K[i] = load_le<u64bit>(key, i);
00240 
00241    m_K[8] = m_K[0] ^ m_K[1] ^ m_K[2] ^ m_K[3] ^
00242             m_K[4] ^ m_K[5] ^ m_K[6] ^ m_K[7] ^ 0x1BD11BDAA9FC1A22;
00243 
00244    // Reset tweak to all zeros on key reset
00245    m_T.resize(3);
00246    zeroise(m_T);
00247    }
00248 
00249 void Threefish_512::clear()
00250    {
00251    zeroise(m_K);
00252    zeroise(m_T);
00253    }
00254 
00255 }