void Stateful_RNG::randomize_with_ts_input(uint8_t output[], size_t output_len) { uint8_t additional_input[24] = { 0 }; store_le(OS::get_system_timestamp_ns(), additional_input); store_le(OS::get_processor_timestamp(), additional_input + 8); store_le(m_last_pid, additional_input + 16); store_le(static_cast<uint32_t>(m_reseed_counter), additional_input + 20); randomize_with_input(output, output_len, additional_input, sizeof(additional_input)); }
void RandomNumberGenerator::randomize_with_ts_input(uint8_t output[], size_t output_len) { /* Form additional input which is provided to the PRNG implementation to paramaterize the KDF output. */ uint8_t additional_input[16] = { 0 }; store_le(OS::get_system_timestamp_ns(), additional_input); store_le(OS::get_high_resolution_clock(), additional_input + 8); randomize_with_input(output, output_len, additional_input, sizeof(additional_input)); }
/* * GOST Decryption */ void GOST_28147_89::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit N1 = load_le<u32bit>(in, 0); u32bit N2 = load_le<u32bit>(in, 1); GOST_2ROUND(N1, N2, 0, 1); GOST_2ROUND(N1, N2, 2, 3); GOST_2ROUND(N1, N2, 4, 5); GOST_2ROUND(N1, N2, 6, 7); for(size_t j = 0; j != 3; ++j) { GOST_2ROUND(N1, N2, 7, 6); GOST_2ROUND(N1, N2, 5, 4); GOST_2ROUND(N1, N2, 3, 2); GOST_2ROUND(N1, N2, 1, 0); } store_le(out, N2, N1); in += BLOCK_SIZE; out += BLOCK_SIZE; } }
void Threefish_512::encrypt_n(const byte in[], byte out[], size_t blocks) const { BOTAN_ASSERT(m_K.size() == 9, "Key was set"); BOTAN_ASSERT(m_T.size() == 3, "Tweak was set"); for(size_t i = 0; i != blocks; ++i) { u64bit X0 = load_le<u64bit>(in, 0); u64bit X1 = load_le<u64bit>(in, 1); u64bit X2 = load_le<u64bit>(in, 2); u64bit X3 = load_le<u64bit>(in, 3); u64bit X4 = load_le<u64bit>(in, 4); u64bit X5 = load_le<u64bit>(in, 5); u64bit X6 = load_le<u64bit>(in, 6); u64bit X7 = load_le<u64bit>(in, 7); THREEFISH_INJECT_KEY(0); THREEFISH_ENC_8_ROUNDS(1,2); THREEFISH_ENC_8_ROUNDS(3,4); THREEFISH_ENC_8_ROUNDS(5,6); THREEFISH_ENC_8_ROUNDS(7,8); THREEFISH_ENC_8_ROUNDS(9,10); THREEFISH_ENC_8_ROUNDS(11,12); THREEFISH_ENC_8_ROUNDS(13,14); THREEFISH_ENC_8_ROUNDS(15,16); THREEFISH_ENC_8_ROUNDS(17,18); store_le(out, X0, X1, X2, X3, X4, X5, X6, X7); in += 64; out += 64; } }
/* * RC2 Encryption */ void RC2::enc(const byte in[], byte out[]) const { u16bit R0 = load_le<u16bit>(in, 0); u16bit R1 = load_le<u16bit>(in, 1); u16bit R2 = load_le<u16bit>(in, 2); u16bit R3 = load_le<u16bit>(in, 3); for(u32bit j = 0; j != 16; ++j) { R0 += (R1 & ~R3) + (R2 & R3) + K[4*j]; R0 = rotate_left(R0, 1); R1 += (R2 & ~R0) + (R3 & R0) + K[4*j + 1]; R1 = rotate_left(R1, 2); R2 += (R3 & ~R1) + (R0 & R1) + K[4*j + 2]; R2 = rotate_left(R2, 3); R3 += (R0 & ~R2) + (R1 & R2) + K[4*j + 3]; R3 = rotate_left(R3, 5); if(j == 4 || j == 10) { R0 += K[R3 % 64]; R1 += K[R0 % 64]; R2 += K[R1 % 64]; R3 += K[R2 % 64]; } } store_le(out, R0, R1, R2, R3); }
void Threefish_512::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const { BOTAN_ASSERT(m_K.size() == 9, "Key was set"); BOTAN_ASSERT(m_T.size() == 3, "Tweak was set"); #if defined(BOTAN_HAS_THREEFISH_512_AVX2) if(CPUID::has_avx2()) { return avx2_encrypt_n(in, out, blocks); } #endif BOTAN_PARALLEL_FOR(size_t i = 0; i < blocks; ++i) { uint64_t X0, X1, X2, X3, X4, X5, X6, X7; load_le(in + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7); THREEFISH_INJECT_KEY(0); THREEFISH_ENC_8_ROUNDS(1,2); THREEFISH_ENC_8_ROUNDS(3,4); THREEFISH_ENC_8_ROUNDS(5,6); THREEFISH_ENC_8_ROUNDS(7,8); THREEFISH_ENC_8_ROUNDS(9,10); THREEFISH_ENC_8_ROUNDS(11,12); THREEFISH_ENC_8_ROUNDS(13,14); THREEFISH_ENC_8_ROUNDS(15,16); THREEFISH_ENC_8_ROUNDS(17,18); store_le(out + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7); } }
/* * RC2 Decryption */ void RC2::dec(const byte in[], byte out[]) const { u16bit R0 = load_le<u16bit>(in, 0); u16bit R1 = load_le<u16bit>(in, 1); u16bit R2 = load_le<u16bit>(in, 2); u16bit R3 = load_le<u16bit>(in, 3); for(u32bit j = 0; j != 16; ++j) { R3 = rotate_right(R3, 5); R3 -= (R0 & ~R2) + (R1 & R2) + K[63 - (4*j + 0)]; R2 = rotate_right(R2, 3); R2 -= (R3 & ~R1) + (R0 & R1) + K[63 - (4*j + 1)]; R1 = rotate_right(R1, 2); R1 -= (R2 & ~R0) + (R3 & R0) + K[63 - (4*j + 2)]; R0 = rotate_right(R0, 1); R0 -= (R1 & ~R3) + (R2 & R3) + K[63 - (4*j + 3)]; if(j == 4 || j == 10) { R3 -= K[R2 % 64]; R2 -= K[R1 % 64]; R1 -= K[R0 % 64]; R0 -= K[R3 % 64]; } } store_le(out, R0, R1, R2, R3); }
/* * Write the count bits to the buffer */ void MDx_HashFunction::write_count(uint8_t out[]) { if(COUNT_SIZE < 8) throw Invalid_State("MDx_HashFunction::write_count: COUNT_SIZE < 8"); if(COUNT_SIZE >= output_length() || COUNT_SIZE >= hash_block_size()) throw Invalid_Argument("MDx_HashFunction: COUNT_SIZE is too big"); const uint64_t bit_count = m_count * 8; if(BIG_BYTE_ENDIAN) store_be(bit_count, out + COUNT_SIZE - 8); else store_le(bit_count, out + COUNT_SIZE - 8); }
/* * Twofish Encryption */ void Twofish::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit A = load_le<u32bit>(in, 0) ^ RK[0]; u32bit B = load_le<u32bit>(in, 1) ^ RK[1]; u32bit C = load_le<u32bit>(in, 2) ^ RK[2]; u32bit D = load_le<u32bit>(in, 3) ^ RK[3]; for(size_t j = 0; j != 16; j += 2) { u32bit X, Y; X = SB[ get_byte(3, A)] ^ SB[256+get_byte(2, A)] ^ SB[512+get_byte(1, A)] ^ SB[768+get_byte(0, A)]; Y = SB[ get_byte(0, B)] ^ SB[256+get_byte(3, B)] ^ SB[512+get_byte(2, B)] ^ SB[768+get_byte(1, B)]; X += Y; Y += X + RK[2*j + 9]; X += RK[2*j + 8]; C = rotate_right(C ^ X, 1); D = rotate_left(D, 1) ^ Y; X = SB[ get_byte(3, C)] ^ SB[256+get_byte(2, C)] ^ SB[512+get_byte(1, C)] ^ SB[768+get_byte(0, C)]; Y = SB[ get_byte(0, D)] ^ SB[256+get_byte(3, D)] ^ SB[512+get_byte(2, D)] ^ SB[768+get_byte(1, D)]; X += Y; Y += X + RK[2*j + 11]; X += RK[2*j + 10]; A = rotate_right(A ^ X, 1); B = rotate_left(B, 1) ^ Y; } C ^= RK[4]; D ^= RK[5]; A ^= RK[6]; B ^= RK[7]; store_le(out, C, D, A, B); in += BLOCK_SIZE; out += BLOCK_SIZE; } }
/* * Twofish Decryption */ void Twofish::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit A = load_le<u32bit>(in, 0) ^ m_RK[4]; u32bit B = load_le<u32bit>(in, 1) ^ m_RK[5]; u32bit C = load_le<u32bit>(in, 2) ^ m_RK[6]; u32bit D = load_le<u32bit>(in, 3) ^ m_RK[7]; for(size_t j = 0; j != 16; j += 2) { u32bit X, Y; X = m_SB[ get_byte(3, A)] ^ m_SB[256+get_byte(2, A)] ^ m_SB[512+get_byte(1, A)] ^ m_SB[768+get_byte(0, A)]; Y = m_SB[ get_byte(0, B)] ^ m_SB[256+get_byte(3, B)] ^ m_SB[512+get_byte(2, B)] ^ m_SB[768+get_byte(1, B)]; X += Y; Y += X + m_RK[39 - 2*j]; X += m_RK[38 - 2*j]; C = rotate_left(C, 1) ^ X; D = rotate_right(D ^ Y, 1); X = m_SB[ get_byte(3, C)] ^ m_SB[256+get_byte(2, C)] ^ m_SB[512+get_byte(1, C)] ^ m_SB[768+get_byte(0, C)]; Y = m_SB[ get_byte(0, D)] ^ m_SB[256+get_byte(3, D)] ^ m_SB[512+get_byte(2, D)] ^ m_SB[768+get_byte(1, D)]; X += Y; Y += X + m_RK[37 - 2*j]; X += m_RK[36 - 2*j]; A = rotate_left(A, 1) ^ X; B = rotate_right(B ^ Y, 1); } C ^= m_RK[0]; D ^= m_RK[1]; A ^= m_RK[2]; B ^= m_RK[3]; store_le(out, C, D, A, B); in += BLOCK_SIZE; out += BLOCK_SIZE; } }
void RDRAND_RNG::randomize(uint8_t out[], size_t out_len) { while(out_len >= 4) { uint32_t r = RDRAND_RNG::rdrand(); store_le(r, out); out += 4; out_len -= 4; } if(out_len) // between 1 and 3 trailing bytes { uint32_t r = RDRAND_RNG::rdrand(); for(size_t i = 0; i != out_len; ++i) out[i] = get_byte(i, r); } }
/* * RC6 Encryption */ void RC6::encrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit A = load_le<u32bit>(in, 0); u32bit B = load_le<u32bit>(in, 1); u32bit C = load_le<u32bit>(in, 2); u32bit D = load_le<u32bit>(in, 3); B += S[0]; D += S[1]; for(size_t j = 0; j != 20; j += 4) { u32bit T1, T2; T1 = rotate_left(B*(2*B+1), 5); T2 = rotate_left(D*(2*D+1), 5); A = rotate_left(A ^ T1, T2 % 32) + S[2*j+2]; C = rotate_left(C ^ T2, T1 % 32) + S[2*j+3]; T1 = rotate_left(C*(2*C+1), 5); T2 = rotate_left(A*(2*A+1), 5); B = rotate_left(B ^ T1, T2 % 32) + S[2*j+4]; D = rotate_left(D ^ T2, T1 % 32) + S[2*j+5]; T1 = rotate_left(D*(2*D+1), 5); T2 = rotate_left(B*(2*B+1), 5); C = rotate_left(C ^ T1, T2 % 32) + S[2*j+6]; A = rotate_left(A ^ T2, T1 % 32) + S[2*j+7]; T1 = rotate_left(A*(2*A+1), 5); T2 = rotate_left(C*(2*C+1), 5); D = rotate_left(D ^ T1, T2 % 32) + S[2*j+8]; B = rotate_left(B ^ T2, T1 % 32) + S[2*j+9]; } A += S[42]; C += S[43]; store_le(out, A, B, C, D); in += BLOCK_SIZE; out += BLOCK_SIZE; } }
/* * RC6 Decryption */ void RC6::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u32bit A = load_le<u32bit>(in, 0); u32bit B = load_le<u32bit>(in, 1); u32bit C = load_le<u32bit>(in, 2); u32bit D = load_le<u32bit>(in, 3); C -= S[43]; A -= S[42]; for(size_t j = 0; j != 20; j += 4) { u32bit T1, T2; T1 = rotate_left(A*(2*A+1), 5); T2 = rotate_left(C*(2*C+1), 5); B = rotate_right(B - S[41 - 2*j], T1 % 32) ^ T2; D = rotate_right(D - S[40 - 2*j], T2 % 32) ^ T1; T1 = rotate_left(D*(2*D+1), 5); T2 = rotate_left(B*(2*B+1), 5); A = rotate_right(A - S[39 - 2*j], T1 % 32) ^ T2; C = rotate_right(C - S[38 - 2*j], T2 % 32) ^ T1; T1 = rotate_left(C*(2*C+1), 5); T2 = rotate_left(A*(2*A+1), 5); D = rotate_right(D - S[37 - 2*j], T1 % 32) ^ T2; B = rotate_right(B - S[36 - 2*j], T2 % 32) ^ T1; T1 = rotate_left(B*(2*B+1), 5); T2 = rotate_left(D*(2*D+1), 5); C = rotate_right(C - S[35 - 2*j], T1 % 32) ^ T2; A = rotate_right(A - S[34 - 2*j], T2 % 32) ^ T1; } D -= S[1]; B -= S[0]; store_le(out, A, B, C, D); in += BLOCK_SIZE; out += BLOCK_SIZE; } }
/* * GOST Encryption */ void GOST_28147_89::enc(const byte in[], byte out[]) const { u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1); for(size_t i = 0; i != 3; ++i) { GOST_2ROUND(N1, N2, 0, 1); GOST_2ROUND(N1, N2, 2, 3); GOST_2ROUND(N1, N2, 4, 5); GOST_2ROUND(N1, N2, 6, 7); } GOST_2ROUND(N1, N2, 7, 6); GOST_2ROUND(N1, N2, 5, 4); GOST_2ROUND(N1, N2, 3, 2); GOST_2ROUND(N1, N2, 1, 0); store_le(out, N2, N1); }
/* * Finalize a hash */ void Streebog::final_result(uint8_t output[]) { m_buffer[m_position++] = 0x01; if(m_position != m_buffer.size()) clear_mem(&m_buffer[m_position], m_buffer.size() - m_position); compress(m_buffer.data()); m_count += (m_position - 1) * 8; zeroise(m_buffer); store_le(m_count, m_buffer.data()); compress(m_buffer.data(), true); compress_64(m_S.data(), true); // FIXME std::memcpy(output, &m_h[8 - output_length() / 8], output_length()); clear(); }
void ChaCha::seek(u64bit offset) { if (m_state.size() == 0 && m_buffer.size() == 0) { throw Invalid_State("You have to setup the stream cipher (key and iv)"); } // Find the block offset u64bit counter = offset / 64; byte out[8]; store_le(counter, out); m_state[12] = load_le<u32bit>(out, 0); m_state[13] += load_le<u32bit>(out, 1); chacha_x4(m_buffer.data(), m_state.data(), m_rounds); m_position = offset % 64; }
/** * Produce the final GOST 34.11 output */ void GOST_34_11::final_result(uint8_t out[]) { if(m_position) { clear_mem(m_buffer.data() + m_position, m_buffer.size() - m_position); compress_n(m_buffer.data(), 1); } secure_vector<uint8_t> length_buf(32); const uint64_t bit_count = m_count * 8; store_le(bit_count, length_buf.data()); secure_vector<uint8_t> sum_buf = m_sum; compress_n(length_buf.data(), 1); compress_n(sum_buf.data(), 1); copy_mem(out, m_hash.data(), 32); clear(); }
/** * Produce the final GOST 34.11 output */ void GOST_34_11::final_result(byte out[]) { if(position) { clear_mem(buffer.begin() + position, buffer.size() - position); compress_n(buffer, 1); } SecureBuffer<byte, 32> length_buf; const u64bit bit_count = count * 8; store_le(bit_count, length_buf); SecureBuffer<byte, 32> sum_buf(sum); compress_n(length_buf, 1); compress_n(sum_buf, 1); copy_mem(out, hash.begin(), 32); clear(); }
/* * RC6 Decryption */ void RC6::dec(const byte in[], byte out[]) const { u32bit A = load_le<u32bit>(in, 0); u32bit B = load_le<u32bit>(in, 1); u32bit C = load_le<u32bit>(in, 2); u32bit D = load_le<u32bit>(in, 3); C -= S[43]; A -= S[42]; for(u32bit j = 0; j != 20; j += 4) { u32bit T1, T2; T1 = rotate_left(A*(2*A+1), 5); T2 = rotate_left(C*(2*C+1), 5); B = rotate_right(B - S[41 - 2*j], T1 % 32) ^ T2; D = rotate_right(D - S[40 - 2*j], T2 % 32) ^ T1; T1 = rotate_left(D*(2*D+1), 5); T2 = rotate_left(B*(2*B+1), 5); A = rotate_right(A - S[39 - 2*j], T1 % 32) ^ T2; C = rotate_right(C - S[38 - 2*j], T2 % 32) ^ T1; T1 = rotate_left(C*(2*C+1), 5); T2 = rotate_left(A*(2*A+1), 5); D = rotate_right(D - S[37 - 2*j], T1 % 32) ^ T2; B = rotate_right(B - S[36 - 2*j], T2 % 32) ^ T1; T1 = rotate_left(B*(2*B+1), 5); T2 = rotate_left(D*(2*D+1), 5); C = rotate_right(C - S[35 - 2*j], T1 % 32) ^ T2; A = rotate_right(A - S[34 - 2*j], T2 % 32) ^ T1; } D -= S[1]; B -= S[0]; store_le(out, A, B, C, D); }
/* * RC6 Encryption */ void RC6::enc(const byte in[], byte out[]) const { u32bit A = load_le<u32bit>(in, 0); u32bit B = load_le<u32bit>(in, 1); u32bit C = load_le<u32bit>(in, 2); u32bit D = load_le<u32bit>(in, 3); B += S[0]; D += S[1]; for(u32bit j = 0; j != 20; j += 4) { u32bit T1, T2; T1 = rotate_left(B*(2*B+1), 5); T2 = rotate_left(D*(2*D+1), 5); A = rotate_left(A ^ T1, T2 % 32) + S[2*j+2]; C = rotate_left(C ^ T2, T1 % 32) + S[2*j+3]; T1 = rotate_left(C*(2*C+1), 5); T2 = rotate_left(A*(2*A+1), 5); B = rotate_left(B ^ T1, T2 % 32) + S[2*j+4]; D = rotate_left(D ^ T2, T1 % 32) + S[2*j+5]; T1 = rotate_left(D*(2*D+1), 5); T2 = rotate_left(B*(2*B+1), 5); C = rotate_left(C ^ T1, T2 % 32) + S[2*j+6]; A = rotate_left(A ^ T2, T1 % 32) + S[2*j+7]; T1 = rotate_left(A*(2*A+1), 5); T2 = rotate_left(C*(2*C+1), 5); D = rotate_left(D ^ T1, T2 % 32) + S[2*j+8]; B = rotate_left(B ^ T2, T1 % 32) + S[2*j+9]; } A += S[42]; C += S[43]; store_le(out, A, B, C, D); }
/* * RC2 Decryption */ void RC2::decrypt_n(const byte in[], byte out[], size_t blocks) const { for(size_t i = 0; i != blocks; ++i) { u16bit R0 = load_le<u16bit>(in, 0); u16bit R1 = load_le<u16bit>(in, 1); u16bit R2 = load_le<u16bit>(in, 2); u16bit R3 = load_le<u16bit>(in, 3); for(size_t j = 0; j != 16; ++j) { R3 = rotate_right(R3, 5); R3 -= (R0 & ~R2) + (R1 & R2) + K[63 - (4*j + 0)]; R2 = rotate_right(R2, 3); R2 -= (R3 & ~R1) + (R0 & R1) + K[63 - (4*j + 1)]; R1 = rotate_right(R1, 2); R1 -= (R2 & ~R0) + (R3 & R0) + K[63 - (4*j + 2)]; R0 = rotate_right(R0, 1); R0 -= (R1 & ~R3) + (R2 & R3) + K[63 - (4*j + 3)]; if(j == 4 || j == 10) { R3 -= K[R2 % 64]; R2 -= K[R1 % 64]; R1 -= K[R0 % 64]; R0 -= K[R3 % 64]; } } store_le(out, R0, R1, R2, R3); in += BLOCK_SIZE; out += BLOCK_SIZE; } }
void Threefish_512::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const { BOTAN_ASSERT(m_K.size() == 9, "Key was set"); BOTAN_ASSERT(m_T.size() == 3, "Tweak was set"); #if defined(BOTAN_HAS_THREEFISH_512_AVX2) if(CPUID::has_avx2()) { return avx2_decrypt_n(in, out, blocks); } #endif #define THREEFISH_ROUND(X0,X1,X2,X3,X4,X5,X6,X7,ROT1,ROT2,ROT3,ROT4) \ do { \ X4 ^= X0; \ X5 ^= X1; \ X6 ^= X2; \ X7 ^= X3; \ X4 = rotate_right(X4, ROT1); \ X5 = rotate_right(X5, ROT2); \ X6 = rotate_right(X6, ROT3); \ X7 = rotate_right(X7, ROT4); \ X0 -= X4; \ X1 -= X5; \ X2 -= X6; \ X3 -= X7; \ } while(0) #define THREEFISH_INJECT_KEY(r) \ do { \ X0 -= m_K[(r ) % 9]; \ X1 -= m_K[(r+1) % 9]; \ X2 -= m_K[(r+2) % 9]; \ X3 -= m_K[(r+3) % 9]; \ X4 -= m_K[(r+4) % 9]; \ X5 -= m_K[(r+5) % 9] + m_T[(r ) % 3]; \ X6 -= m_K[(r+6) % 9] + m_T[(r+1) % 3]; \ X7 -= m_K[(r+7) % 9] + (r); \ } while(0) #define THREEFISH_DEC_8_ROUNDS(R1,R2) \ do { \ THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 8,35,56,22); \ THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 25,29,39,43); \ THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 13,50,10,17); \ THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 39,30,34,24); \ THREEFISH_INJECT_KEY(R1); \ \ THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 44, 9,54,56); \ THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 17,49,36,39); \ THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 33,27,14,42); \ THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 46,36,19,37); \ THREEFISH_INJECT_KEY(R2); \ } while(0) BOTAN_PARALLEL_FOR(size_t i = 0; i < blocks; ++i) { uint64_t X0, X1, X2, X3, X4, X5, X6, X7; load_le(in + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7); THREEFISH_INJECT_KEY(18); THREEFISH_DEC_8_ROUNDS(17,16); THREEFISH_DEC_8_ROUNDS(15,14); THREEFISH_DEC_8_ROUNDS(13,12); THREEFISH_DEC_8_ROUNDS(11,10); THREEFISH_DEC_8_ROUNDS(9,8); THREEFISH_DEC_8_ROUNDS(7,6); THREEFISH_DEC_8_ROUNDS(5,4); THREEFISH_DEC_8_ROUNDS(3,2); THREEFISH_DEC_8_ROUNDS(1,0); store_le(out + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7); } #undef THREEFISH_DEC_8_ROUNDS #undef THREEFISH_INJECT_KEY #undef THREEFISH_ROUND }
/* * Copy out the digest */ void MD5::copy_out(byte output[]) { for(size_t i = 0; i != output_length(); i += 4) store_le(digest[i/4], output + i); }
void ChaCha::chacha(byte output[64], const u32bit input[16]) { u32bit x00 = input[ 0], x01 = input[ 1], x02 = input[ 2], x03 = input[ 3], x04 = input[ 4], x05 = input[ 5], x06 = input[ 6], x07 = input[ 7], x08 = input[ 8], x09 = input[ 9], x10 = input[10], x11 = input[11], x12 = input[12], x13 = input[13], x14 = input[14], x15 = input[15]; #define CHACHA_QUARTER_ROUND(a, b, c, d) \ do { \ a += b; d ^= a; d = rotate_left(d, 16); \ c += d; b ^= c; b = rotate_left(b, 12); \ a += b; d ^= a; d = rotate_left(d, 8); \ c += d; b ^= c; b = rotate_left(b, 7); \ } while(0) for(size_t i = 0; i != 10; ++i) { CHACHA_QUARTER_ROUND(x00, x04, x08, x12); CHACHA_QUARTER_ROUND(x01, x05, x09, x13); CHACHA_QUARTER_ROUND(x02, x06, x10, x14); CHACHA_QUARTER_ROUND(x03, x07, x11, x15); CHACHA_QUARTER_ROUND(x00, x05, x10, x15); CHACHA_QUARTER_ROUND(x01, x06, x11, x12); CHACHA_QUARTER_ROUND(x02, x07, x08, x13); CHACHA_QUARTER_ROUND(x03, x04, x09, x14); } #undef CHACHA_QUARTER_ROUND store_le(x00 + input[ 0], output + 4 * 0); store_le(x01 + input[ 1], output + 4 * 1); store_le(x02 + input[ 2], output + 4 * 2); store_le(x03 + input[ 3], output + 4 * 3); store_le(x04 + input[ 4], output + 4 * 4); store_le(x05 + input[ 5], output + 4 * 5); store_le(x06 + input[ 6], output + 4 * 6); store_le(x07 + input[ 7], output + 4 * 7); store_le(x08 + input[ 8], output + 4 * 8); store_le(x09 + input[ 9], output + 4 * 9); store_le(x10 + input[10], output + 4 * 10); store_le(x11 + input[11], output + 4 * 11); store_le(x12 + input[12], output + 4 * 12); store_le(x13 + input[13], output + 4 * 13); store_le(x14 + input[14], output + 4 * 14); store_le(x15 + input[15], output + 4 * 15); }
//static void ChaCha::chacha_x4(byte output[64*4], u32bit input[16], size_t rounds) { BOTAN_ASSERT(rounds % 2 == 0, "Valid rounds"); #if defined(BOTAN_HAS_CHACHA_SSE2) if(CPUID::has_sse2()) { return ChaCha::chacha_sse2_x4(output, input, rounds); } #endif // TODO interleave rounds for(size_t i = 0; i != 4; ++i) { u32bit x00 = input[ 0], x01 = input[ 1], x02 = input[ 2], x03 = input[ 3], x04 = input[ 4], x05 = input[ 5], x06 = input[ 6], x07 = input[ 7], x08 = input[ 8], x09 = input[ 9], x10 = input[10], x11 = input[11], x12 = input[12], x13 = input[13], x14 = input[14], x15 = input[15]; #define CHACHA_QUARTER_ROUND(a, b, c, d) \ do { \ a += b; d ^= a; d = rotate_left(d, 16); \ c += d; b ^= c; b = rotate_left(b, 12); \ a += b; d ^= a; d = rotate_left(d, 8); \ c += d; b ^= c; b = rotate_left(b, 7); \ } while(0) for(size_t r = 0; r != rounds / 2; ++r) { CHACHA_QUARTER_ROUND(x00, x04, x08, x12); CHACHA_QUARTER_ROUND(x01, x05, x09, x13); CHACHA_QUARTER_ROUND(x02, x06, x10, x14); CHACHA_QUARTER_ROUND(x03, x07, x11, x15); CHACHA_QUARTER_ROUND(x00, x05, x10, x15); CHACHA_QUARTER_ROUND(x01, x06, x11, x12); CHACHA_QUARTER_ROUND(x02, x07, x08, x13); CHACHA_QUARTER_ROUND(x03, x04, x09, x14); } #undef CHACHA_QUARTER_ROUND x00 += input[0]; x01 += input[1]; x02 += input[2]; x03 += input[3]; x04 += input[4]; x05 += input[5]; x06 += input[6]; x07 += input[7]; x08 += input[8]; x09 += input[9]; x10 += input[10]; x11 += input[11]; x12 += input[12]; x13 += input[13]; x14 += input[14]; x15 += input[15]; store_le(x00, output + 64 * i + 4 * 0); store_le(x01, output + 64 * i + 4 * 1); store_le(x02, output + 64 * i + 4 * 2); store_le(x03, output + 64 * i + 4 * 3); store_le(x04, output + 64 * i + 4 * 4); store_le(x05, output + 64 * i + 4 * 5); store_le(x06, output + 64 * i + 4 * 6); store_le(x07, output + 64 * i + 4 * 7); store_le(x08, output + 64 * i + 4 * 8); store_le(x09, output + 64 * i + 4 * 9); store_le(x10, output + 64 * i + 4 * 10); store_le(x11, output + 64 * i + 4 * 11); store_le(x12, output + 64 * i + 4 * 12); store_le(x13, output + 64 * i + 4 * 13); store_le(x14, output + 64 * i + 4 * 14); store_le(x15, output + 64 * i + 4 * 15); input[12]++; input[13] += input[12] < i; // carry? } }
/* * Copy out the digest */ void MD5::copy_out(byte output[]) { for(u32bit j = 0; j != OUTPUT_LENGTH; j += 4) store_le(digest[j/4], output + j); }
void Threefish_512::decrypt_n(const byte in[], byte out[], size_t blocks) const { BOTAN_ASSERT(m_K.size() == 9, "Key was set"); BOTAN_ASSERT(m_T.size() == 3, "Tweak was set"); #define THREEFISH_ROUND(X0,X1,X2,X3,X4,X5,X6,X7,ROT1,ROT2,ROT3,ROT4) \ do { \ X4 ^= X0; \ X5 ^= X1; \ X6 ^= X2; \ X7 ^= X3; \ X4 = rotate_right(X4, ROT1); \ X5 = rotate_right(X5, ROT2); \ X6 = rotate_right(X6, ROT3); \ X7 = rotate_right(X7, ROT4); \ X0 -= X4; \ X1 -= X5; \ X2 -= X6; \ X3 -= X7; \ } while(0) #define THREEFISH_INJECT_KEY(r) \ do { \ X0 -= m_K[(r ) % 9]; \ X1 -= m_K[(r+1) % 9]; \ X2 -= m_K[(r+2) % 9]; \ X3 -= m_K[(r+3) % 9]; \ X4 -= m_K[(r+4) % 9]; \ X5 -= m_K[(r+5) % 9] + m_T[(r ) % 3]; \ X6 -= m_K[(r+6) % 9] + m_T[(r+1) % 3]; \ X7 -= m_K[(r+7) % 9] + (r); \ } while(0) #define THREEFISH_DEC_8_ROUNDS(R1,R2) \ do { \ THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 8,35,56,22); \ THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 25,29,39,43); \ THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 13,50,10,17); \ THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 39,30,34,24); \ THREEFISH_INJECT_KEY(R1); \ \ THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 44, 9,54,56); \ THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 17,49,36,39); \ THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 33,27,14,42); \ THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 46,36,19,37); \ THREEFISH_INJECT_KEY(R2); \ } while(0) for(size_t i = 0; i != blocks; ++i) { u64bit X0 = load_le<u64bit>(in, 0); u64bit X1 = load_le<u64bit>(in, 1); u64bit X2 = load_le<u64bit>(in, 2); u64bit X3 = load_le<u64bit>(in, 3); u64bit X4 = load_le<u64bit>(in, 4); u64bit X5 = load_le<u64bit>(in, 5); u64bit X6 = load_le<u64bit>(in, 6); u64bit X7 = load_le<u64bit>(in, 7); THREEFISH_INJECT_KEY(18); THREEFISH_DEC_8_ROUNDS(17,16); THREEFISH_DEC_8_ROUNDS(15,14); THREEFISH_DEC_8_ROUNDS(13,12); THREEFISH_DEC_8_ROUNDS(11,10); THREEFISH_DEC_8_ROUNDS(9,8); THREEFISH_DEC_8_ROUNDS(7,6); THREEFISH_DEC_8_ROUNDS(5,4); THREEFISH_DEC_8_ROUNDS(3,2); THREEFISH_DEC_8_ROUNDS(1,0); store_le(out, X0, X1, X2, X3, X4, X5, X6, X7); in += 64; out += 64; } #undef THREEFISH_DEC_8_ROUNDS #undef THREEFISH_INJECT_KEY #undef THREEFISH_ROUND }