Botan
1.11.15
|
00001 /* 00002 * Salsa20 / XSalsa20 00003 * (C) 1999-2010,2014 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/internal/stream_utils.h> 00009 #include <botan/salsa20.h> 00010 00011 namespace Botan { 00012 00013 BOTAN_REGISTER_STREAM_CIPHER_NOARGS(Salsa20); 00014 00015 namespace { 00016 00017 #define SALSA20_QUARTER_ROUND(x1, x2, x3, x4) \ 00018 do { \ 00019 x2 ^= rotate_left(x1 + x4, 7); \ 00020 x3 ^= rotate_left(x2 + x1, 9); \ 00021 x4 ^= rotate_left(x3 + x2, 13); \ 00022 x1 ^= rotate_left(x4 + x3, 18); \ 00023 } while(0) 00024 00025 /* 00026 * Generate HSalsa20 cipher stream (for XSalsa20 IV setup) 00027 */ 00028 void hsalsa20(u32bit output[8], const u32bit input[16]) 00029 { 00030 u32bit x00 = input[ 0], x01 = input[ 1], x02 = input[ 2], x03 = input[ 3], 00031 x04 = input[ 4], x05 = input[ 5], x06 = input[ 6], x07 = input[ 7], 00032 x08 = input[ 8], x09 = input[ 9], x10 = input[10], x11 = input[11], 00033 x12 = input[12], x13 = input[13], x14 = input[14], x15 = input[15]; 00034 00035 for(size_t i = 0; i != 10; ++i) 00036 { 00037 SALSA20_QUARTER_ROUND(x00, x04, x08, x12); 00038 SALSA20_QUARTER_ROUND(x05, x09, x13, x01); 00039 SALSA20_QUARTER_ROUND(x10, x14, x02, x06); 00040 SALSA20_QUARTER_ROUND(x15, x03, x07, x11); 00041 00042 SALSA20_QUARTER_ROUND(x00, x01, x02, x03); 00043 SALSA20_QUARTER_ROUND(x05, x06, x07, x04); 00044 SALSA20_QUARTER_ROUND(x10, x11, x08, x09); 00045 SALSA20_QUARTER_ROUND(x15, x12, x13, x14); 00046 } 00047 00048 output[0] = x00; 00049 output[1] = x05; 00050 output[2] = x10; 00051 output[3] = x15; 00052 output[4] = x06; 00053 output[5] = x07; 00054 output[6] = x08; 00055 output[7] = x09; 00056 } 00057 00058 /* 00059 * Generate Salsa20 cipher stream 00060 */ 00061 void salsa20(byte output[64], const u32bit input[16]) 00062 { 00063 u32bit x00 = input[ 0], x01 = input[ 1], x02 = input[ 2], x03 = input[ 3], 00064 x04 = input[ 4], x05 = input[ 5], x06 = input[ 6], x07 = input[ 7], 00065 x08 = input[ 8], x09 = input[ 9], x10 = input[10], x11 = input[11], 00066 x12 = input[12], x13 = input[13], x14 = input[14], x15 = input[15]; 00067 00068 for(size_t i = 0; i != 10; ++i) 00069 { 00070 SALSA20_QUARTER_ROUND(x00, x04, x08, x12); 00071 SALSA20_QUARTER_ROUND(x05, x09, x13, x01); 00072 SALSA20_QUARTER_ROUND(x10, x14, x02, x06); 00073 SALSA20_QUARTER_ROUND(x15, x03, x07, x11); 00074 00075 SALSA20_QUARTER_ROUND(x00, x01, x02, x03); 00076 SALSA20_QUARTER_ROUND(x05, x06, x07, x04); 00077 SALSA20_QUARTER_ROUND(x10, x11, x08, x09); 00078 SALSA20_QUARTER_ROUND(x15, x12, x13, x14); 00079 } 00080 00081 store_le(x00 + input[ 0], output + 4 * 0); 00082 store_le(x01 + input[ 1], output + 4 * 1); 00083 store_le(x02 + input[ 2], output + 4 * 2); 00084 store_le(x03 + input[ 3], output + 4 * 3); 00085 store_le(x04 + input[ 4], output + 4 * 4); 00086 store_le(x05 + input[ 5], output + 4 * 5); 00087 store_le(x06 + input[ 6], output + 4 * 6); 00088 store_le(x07 + input[ 7], output + 4 * 7); 00089 store_le(x08 + input[ 8], output + 4 * 8); 00090 store_le(x09 + input[ 9], output + 4 * 9); 00091 store_le(x10 + input[10], output + 4 * 10); 00092 store_le(x11 + input[11], output + 4 * 11); 00093 store_le(x12 + input[12], output + 4 * 12); 00094 store_le(x13 + input[13], output + 4 * 13); 00095 store_le(x14 + input[14], output + 4 * 14); 00096 store_le(x15 + input[15], output + 4 * 15); 00097 } 00098 00099 } 00100 00101 #undef SALSA20_QUARTER_ROUND 00102 00103 /* 00104 * Combine cipher stream with message 00105 */ 00106 void Salsa20::cipher(const byte in[], byte out[], size_t length) 00107 { 00108 while(length >= m_buffer.size() - m_position) 00109 { 00110 xor_buf(out, in, &m_buffer[m_position], m_buffer.size() - m_position); 00111 length -= (m_buffer.size() - m_position); 00112 in += (m_buffer.size() - m_position); 00113 out += (m_buffer.size() - m_position); 00114 salsa20(&m_buffer[0], &m_state[0]); 00115 00116 ++m_state[8]; 00117 m_state[9] += (m_state[8] == 0); 00118 00119 m_position = 0; 00120 } 00121 00122 xor_buf(out, in, &m_buffer[m_position], length); 00123 00124 m_position += length; 00125 } 00126 00127 /* 00128 * Salsa20 Key Schedule 00129 */ 00130 void Salsa20::key_schedule(const byte key[], size_t length) 00131 { 00132 static const u32bit TAU[] = 00133 { 0x61707865, 0x3120646e, 0x79622d36, 0x6b206574 }; 00134 00135 static const u32bit SIGMA[] = 00136 { 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 }; 00137 00138 const u32bit* CONSTANTS = (length == 16) ? TAU : SIGMA; 00139 00140 m_state.resize(16); 00141 m_buffer.resize(64); 00142 00143 m_state[0] = CONSTANTS[0]; 00144 m_state[5] = CONSTANTS[1]; 00145 m_state[10] = CONSTANTS[2]; 00146 m_state[15] = CONSTANTS[3]; 00147 00148 m_state[1] = load_le<u32bit>(key, 0); 00149 m_state[2] = load_le<u32bit>(key, 1); 00150 m_state[3] = load_le<u32bit>(key, 2); 00151 m_state[4] = load_le<u32bit>(key, 3); 00152 00153 if(length == 32) 00154 key += 16; 00155 00156 m_state[11] = load_le<u32bit>(key, 0); 00157 m_state[12] = load_le<u32bit>(key, 1); 00158 m_state[13] = load_le<u32bit>(key, 2); 00159 m_state[14] = load_le<u32bit>(key, 3); 00160 00161 m_position = 0; 00162 00163 const byte ZERO[8] = { 0 }; 00164 set_iv(ZERO, sizeof(ZERO)); 00165 } 00166 00167 /* 00168 * Return the name of this type 00169 */ 00170 void Salsa20::set_iv(const byte iv[], size_t length) 00171 { 00172 if(!valid_iv_length(length)) 00173 throw Invalid_IV_Length(name(), length); 00174 00175 if(length == 8) 00176 { 00177 // Salsa20 00178 m_state[6] = load_le<u32bit>(iv, 0); 00179 m_state[7] = load_le<u32bit>(iv, 1); 00180 } 00181 else 00182 { 00183 // XSalsa20 00184 m_state[6] = load_le<u32bit>(iv, 0); 00185 m_state[7] = load_le<u32bit>(iv, 1); 00186 m_state[8] = load_le<u32bit>(iv, 2); 00187 m_state[9] = load_le<u32bit>(iv, 3); 00188 00189 secure_vector<u32bit> hsalsa(8); 00190 hsalsa20(&hsalsa[0], &m_state[0]); 00191 00192 m_state[ 1] = hsalsa[0]; 00193 m_state[ 2] = hsalsa[1]; 00194 m_state[ 3] = hsalsa[2]; 00195 m_state[ 4] = hsalsa[3]; 00196 m_state[ 6] = load_le<u32bit>(iv, 4); 00197 m_state[ 7] = load_le<u32bit>(iv, 5); 00198 m_state[11] = hsalsa[4]; 00199 m_state[12] = hsalsa[5]; 00200 m_state[13] = hsalsa[6]; 00201 m_state[14] = hsalsa[7]; 00202 } 00203 00204 m_state[8] = 0; 00205 m_state[9] = 0; 00206 00207 salsa20(&m_buffer[0], &m_state[0]); 00208 ++m_state[8]; 00209 m_state[9] += (m_state[8] == 0); 00210 00211 m_position = 0; 00212 } 00213 00214 /* 00215 * Return the name of this type 00216 */ 00217 std::string Salsa20::name() const 00218 { 00219 return "Salsa20"; 00220 } 00221 00222 /* 00223 * Clear memory of sensitive data 00224 */ 00225 void Salsa20::clear() 00226 { 00227 zap(m_state); 00228 zap(m_buffer); 00229 m_position = 0; 00230 } 00231 00232 }