Botan  1.11.15
src/lib/block/noekeon_simd/noekeon_simd.cpp
Go to the documentation of this file.
00001 /*
00002 * Noekeon in SIMD
00003 * (C) 2010 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_simd.h>
00010 #include <botan/internal/simd_32.h>
00011 
00012 namespace Botan {
00013 
00014 BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(SIMD_32::enabled(), Noekeon_SIMD, "Noekeon", "simd32", 64);
00015 
00016 /*
00017 * Noekeon's Theta Operation
00018 */
00019 #define NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3)  \
00020    do {                                                 \
00021       SIMD_32 T = A0 ^ A2;                              \
00022       SIMD_32 T_l8 = T;                                 \
00023       SIMD_32 T_r8 = T;                                 \
00024       T_l8.rotate_left(8);                              \
00025       T_r8.rotate_right(8);                             \
00026       T ^= T_l8;                                        \
00027       T ^= T_r8;                                        \
00028       A1 ^= T;                                          \
00029       A3 ^= T;                                          \
00030                                                         \
00031       A0 ^= K0;                                         \
00032       A1 ^= K1;                                         \
00033       A2 ^= K2;                                         \
00034       A3 ^= K3;                                         \
00035                                                         \
00036       T = A1 ^ A3;                                      \
00037       T_l8 = T;                                         \
00038       T_r8 = T;                                         \
00039       T_l8.rotate_left(8);                              \
00040       T_r8.rotate_right(8);                             \
00041       T ^= T_l8;                                        \
00042       T ^= T_r8;                                        \
00043       A0 ^= T;                                          \
00044       A2 ^= T;                                          \
00045       } while(0)
00046 
00047 /*
00048 * Noekeon's Gamma S-Box Layer
00049 */
00050 #define NOK_SIMD_GAMMA(A0, A1, A2, A3)                                  \
00051    do                                                                   \
00052       {                                                                 \
00053       A1 ^= A3.andc(~A2);                                               \
00054       A0 ^= A2 & A1;                                                    \
00055                                                                         \
00056       SIMD_32 T = A3;                                                   \
00057       A3 = A0;                                                          \
00058       A0 = T;                                                           \
00059                                                                         \
00060       A2 ^= A0 ^ A1 ^ A3;                                               \
00061                                                                         \
00062       A1 ^= A3.andc(~A2);                                               \
00063       A0 ^= A2 & A1;                                                    \
00064       } while(0)
00065 
00066 /*
00067 * Noekeon Encryption
00068 */
00069 void Noekeon_SIMD::encrypt_n(const byte in[], byte out[], size_t blocks) const
00070    {
00071    const secure_vector<u32bit>& EK = this->get_EK();
00072 
00073    SIMD_32 K0 = SIMD_32(EK[0]);
00074    SIMD_32 K1 = SIMD_32(EK[1]);
00075    SIMD_32 K2 = SIMD_32(EK[2]);
00076    SIMD_32 K3 = SIMD_32(EK[3]);
00077 
00078    while(blocks >= 4)
00079       {
00080       SIMD_32 A0 = SIMD_32::load_be(in     );
00081       SIMD_32 A1 = SIMD_32::load_be(in + 16);
00082       SIMD_32 A2 = SIMD_32::load_be(in + 32);
00083       SIMD_32 A3 = SIMD_32::load_be(in + 48);
00084 
00085       SIMD_32::transpose(A0, A1, A2, A3);
00086 
00087       for(size_t i = 0; i != 16; ++i)
00088          {
00089          A0 ^= SIMD_32(RC[i]);
00090 
00091          NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3);
00092 
00093          A1.rotate_left(1);
00094          A2.rotate_left(5);
00095          A3.rotate_left(2);
00096 
00097          NOK_SIMD_GAMMA(A0, A1, A2, A3);
00098 
00099          A1.rotate_right(1);
00100          A2.rotate_right(5);
00101          A3.rotate_right(2);
00102          }
00103 
00104       A0 ^= SIMD_32(RC[16]);
00105       NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3);
00106 
00107       SIMD_32::transpose(A0, A1, A2, A3);
00108 
00109       A0.store_be(out);
00110       A1.store_be(out + 16);
00111       A2.store_be(out + 32);
00112       A3.store_be(out + 48);
00113 
00114       in += 64;
00115       out += 64;
00116       blocks -= 4;
00117       }
00118 
00119    if(blocks)
00120      Noekeon::encrypt_n(in, out, blocks);
00121    }
00122 
00123 /*
00124 * Noekeon Encryption
00125 */
00126 void Noekeon_SIMD::decrypt_n(const byte in[], byte out[], size_t blocks) const
00127    {
00128    const secure_vector<u32bit>& DK = this->get_DK();
00129 
00130    SIMD_32 K0 = SIMD_32(DK[0]);
00131    SIMD_32 K1 = SIMD_32(DK[1]);
00132    SIMD_32 K2 = SIMD_32(DK[2]);
00133    SIMD_32 K3 = SIMD_32(DK[3]);
00134 
00135    while(blocks >= 4)
00136       {
00137       SIMD_32 A0 = SIMD_32::load_be(in     );
00138       SIMD_32 A1 = SIMD_32::load_be(in + 16);
00139       SIMD_32 A2 = SIMD_32::load_be(in + 32);
00140       SIMD_32 A3 = SIMD_32::load_be(in + 48);
00141 
00142       SIMD_32::transpose(A0, A1, A2, A3);
00143 
00144       for(size_t i = 0; i != 16; ++i)
00145          {
00146          NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3);
00147 
00148          A0 ^= SIMD_32(RC[16-i]);
00149 
00150          A1.rotate_left(1);
00151          A2.rotate_left(5);
00152          A3.rotate_left(2);
00153 
00154          NOK_SIMD_GAMMA(A0, A1, A2, A3);
00155 
00156          A1.rotate_right(1);
00157          A2.rotate_right(5);
00158          A3.rotate_right(2);
00159          }
00160 
00161       NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3);
00162       A0 ^= SIMD_32(RC[0]);
00163 
00164       SIMD_32::transpose(A0, A1, A2, A3);
00165 
00166       A0.store_be(out);
00167       A1.store_be(out + 16);
00168       A2.store_be(out + 32);
00169       A3.store_be(out + 48);
00170 
00171       in += 64;
00172       out += 64;
00173       blocks -= 4;
00174       }
00175 
00176    if(blocks)
00177      Noekeon::decrypt_n(in, out, blocks);
00178    }
00179 
00180 }