Botan
1.11.15
|
00001 /* 00002 * GOST 28147-89 00003 * (C) 1999-2009,2011 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/gost_28147.h> 00010 00011 namespace Botan { 00012 00013 BOTAN_REGISTER_BLOCK_CIPHER_NAMED_1STR(GOST_28147_89, "GOST-28147-89", "R3411_94_TestParam"); 00014 00015 byte GOST_28147_89_Params::sbox_entry(size_t row, size_t col) const 00016 { 00017 byte x = sboxes[4 * col + (row / 2)]; 00018 00019 return (row % 2 == 0) ? (x >> 4) : (x & 0x0F); 00020 } 00021 00022 GOST_28147_89_Params::GOST_28147_89_Params(const std::string& n) : name(n) 00023 { 00024 // Encoded in the packed fromat from RFC 4357 00025 00026 // GostR3411_94_TestParamSet (OID 1.2.643.2.2.31.0) 00027 static const byte GOST_R_3411_TEST_PARAMS[64] = { 00028 0x4E, 0x57, 0x64, 0xD1, 0xAB, 0x8D, 0xCB, 0xBF, 0x94, 0x1A, 0x7A, 00029 0x4D, 0x2C, 0xD1, 0x10, 0x10, 0xD6, 0xA0, 0x57, 0x35, 0x8D, 0x38, 00030 0xF2, 0xF7, 0x0F, 0x49, 0xD1, 0x5A, 0xEA, 0x2F, 0x8D, 0x94, 0x62, 00031 0xEE, 0x43, 0x09, 0xB3, 0xF4, 0xA6, 0xA2, 0x18, 0xC6, 0x98, 0xE3, 00032 0xC1, 0x7C, 0xE5, 0x7E, 0x70, 0x6B, 0x09, 0x66, 0xF7, 0x02, 0x3C, 00033 0x8B, 0x55, 0x95, 0xBF, 0x28, 0x39, 0xB3, 0x2E, 0xCC }; 00034 00035 // GostR3411-94-CryptoProParamSet (OID 1.2.643.2.2.31.1) 00036 static const byte GOST_R_3411_CRYPTOPRO_PARAMS[64] = { 00037 0xA5, 0x74, 0x77, 0xD1, 0x4F, 0xFA, 0x66, 0xE3, 0x54, 0xC7, 0x42, 00038 0x4A, 0x60, 0xEC, 0xB4, 0x19, 0x82, 0x90, 0x9D, 0x75, 0x1D, 0x4F, 00039 0xC9, 0x0B, 0x3B, 0x12, 0x2F, 0x54, 0x79, 0x08, 0xA0, 0xAF, 0xD1, 00040 0x3E, 0x1A, 0x38, 0xC7, 0xB1, 0x81, 0xC6, 0xE6, 0x56, 0x05, 0x87, 00041 0x03, 0x25, 0xEB, 0xFE, 0x9C, 0x6D, 0xF8, 0x6D, 0x2E, 0xAB, 0xDE, 00042 0x20, 0xBA, 0x89, 0x3C, 0x92, 0xF8, 0xD3, 0x53, 0xBC }; 00043 00044 if(name == "R3411_94_TestParam") 00045 sboxes = GOST_R_3411_TEST_PARAMS; 00046 else if(name == "R3411_CryptoPro") 00047 sboxes = GOST_R_3411_CRYPTOPRO_PARAMS; 00048 else 00049 throw Invalid_Argument("GOST_28147_89_Params: Unknown " + name); 00050 } 00051 00052 /* 00053 * GOST Constructor 00054 */ 00055 GOST_28147_89::GOST_28147_89(const GOST_28147_89_Params& param) : SBOX(1024) 00056 { 00057 // Convert the parallel 4x4 sboxes into larger word-based sboxes 00058 for(size_t i = 0; i != 4; ++i) 00059 for(size_t j = 0; j != 256; ++j) 00060 { 00061 const u32bit T = (param.sbox_entry(2*i , j % 16)) | 00062 (param.sbox_entry(2*i+1, j / 16) << 4); 00063 SBOX[256*i+j] = rotate_left(T, (11+8*i) % 32); 00064 } 00065 } 00066 00067 std::string GOST_28147_89::name() const 00068 { 00069 /* 00070 'Guess' the right name for the sbox on the basis of the values. 00071 This would need to be updated if support for other sbox parameters 00072 is added. Preferably, we would just store the string value in the 00073 constructor, but can't break binary compat. 00074 */ 00075 std::string sbox_name = ""; 00076 if(SBOX[0] == 0x00072000) 00077 sbox_name = "R3411_94_TestParam"; 00078 else if(SBOX[0] == 0x0002D000) 00079 sbox_name = "R3411_CryptoPro"; 00080 else 00081 throw Internal_Error("GOST-28147 unrecognized sbox value"); 00082 00083 return "GOST-28147-89(" + sbox_name + ")"; 00084 } 00085 00086 /* 00087 * Two rounds of GOST 00088 */ 00089 #define GOST_2ROUND(N1, N2, R1, R2) \ 00090 do { \ 00091 u32bit T0 = N1 + EK[R1]; \ 00092 N2 ^= SBOX[get_byte(3, T0)] | \ 00093 SBOX[get_byte(2, T0)+256] | \ 00094 SBOX[get_byte(1, T0)+512] | \ 00095 SBOX[get_byte(0, T0)+768]; \ 00096 \ 00097 u32bit T1 = N2 + EK[R2]; \ 00098 N1 ^= SBOX[get_byte(3, T1)] | \ 00099 SBOX[get_byte(2, T1)+256] | \ 00100 SBOX[get_byte(1, T1)+512] | \ 00101 SBOX[get_byte(0, T1)+768]; \ 00102 } while(0) 00103 00104 /* 00105 * GOST Encryption 00106 */ 00107 void GOST_28147_89::encrypt_n(const byte in[], byte out[], size_t blocks) const 00108 { 00109 for(size_t i = 0; i != blocks; ++i) 00110 { 00111 u32bit N1 = load_le<u32bit>(in, 0); 00112 u32bit N2 = load_le<u32bit>(in, 1); 00113 00114 for(size_t j = 0; j != 3; ++j) 00115 { 00116 GOST_2ROUND(N1, N2, 0, 1); 00117 GOST_2ROUND(N1, N2, 2, 3); 00118 GOST_2ROUND(N1, N2, 4, 5); 00119 GOST_2ROUND(N1, N2, 6, 7); 00120 } 00121 00122 GOST_2ROUND(N1, N2, 7, 6); 00123 GOST_2ROUND(N1, N2, 5, 4); 00124 GOST_2ROUND(N1, N2, 3, 2); 00125 GOST_2ROUND(N1, N2, 1, 0); 00126 00127 store_le(out, N2, N1); 00128 00129 in += BLOCK_SIZE; 00130 out += BLOCK_SIZE; 00131 } 00132 } 00133 00134 /* 00135 * GOST Decryption 00136 */ 00137 void GOST_28147_89::decrypt_n(const byte in[], byte out[], size_t blocks) const 00138 { 00139 for(size_t i = 0; i != blocks; ++i) 00140 { 00141 u32bit N1 = load_le<u32bit>(in, 0); 00142 u32bit N2 = load_le<u32bit>(in, 1); 00143 00144 GOST_2ROUND(N1, N2, 0, 1); 00145 GOST_2ROUND(N1, N2, 2, 3); 00146 GOST_2ROUND(N1, N2, 4, 5); 00147 GOST_2ROUND(N1, N2, 6, 7); 00148 00149 for(size_t j = 0; j != 3; ++j) 00150 { 00151 GOST_2ROUND(N1, N2, 7, 6); 00152 GOST_2ROUND(N1, N2, 5, 4); 00153 GOST_2ROUND(N1, N2, 3, 2); 00154 GOST_2ROUND(N1, N2, 1, 0); 00155 } 00156 00157 store_le(out, N2, N1); 00158 in += BLOCK_SIZE; 00159 out += BLOCK_SIZE; 00160 } 00161 } 00162 00163 /* 00164 * GOST Key Schedule 00165 */ 00166 void GOST_28147_89::key_schedule(const byte key[], size_t) 00167 { 00168 EK.resize(8); 00169 for(size_t i = 0; i != 8; ++i) 00170 EK[i] = load_le<u32bit>(key, i); 00171 } 00172 00173 void GOST_28147_89::clear() 00174 { 00175 zap(EK); 00176 } 00177 00178 }