Botan
1.11.15
|
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 }