Skip to content

Commit

Permalink
Basic Twofish implementation added #41
Browse files Browse the repository at this point in the history
  • Loading branch information
nkaskov committed Jun 24, 2020
1 parent a84f3ba commit dcf7b8c
Show file tree
Hide file tree
Showing 6 changed files with 752 additions and 0 deletions.
304 changes: 304 additions & 0 deletions include/nil/crypto3/block/detail/twofish/basic_twofish_policy.hpp

Large diffs are not rendered by default.

76 changes: 76 additions & 0 deletions include/nil/crypto3/block/detail/twofish/twofish_functions.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//---------------------------------------------------------------------------//
// Copyright (c) 2018-2020 Mikhail Komarov <nemo@nil.foundation>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//---------------------------------------------------------------------------//

#ifndef CRYPTO3_TWOFISH_FUNCTIONS_CPP_HPP
#define CRYPTO3_TWOFISH_FUNCTIONS_CPP_HPP

#include <nil/crypto3/block/detail/twofish/basic_twofish_policy.hpp>

#include <nil/crypto3/detail/basic_functions.hpp>
#include <nil/crypto3/detail/make_uint_t.hpp>

namespace nil {
namespace crypto3 {
namespace block {
namespace detail {
template<std::size_t KeyBits>
struct twofish_functions : public basic_twofish_policy<KeyBits> {
typedef basic_twofish_policy<KeyBits> policy_type;
typedef typename policy_type::word_type word_type;

typedef
typename basic_twofish_policy<KeyBits>::expanded_substitution_type expanded_substitution_type;

inline static void tf_e(word_type A, word_type B, word_type &C, word_type &D, word_type RK1,
word_type RK2, const expanded_substitution_type &SB) {
word_type X = SB[::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(A, 3)] ^
SB[512 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(A, 1)] ^
SB[256 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(A, 2)] ^
SB[768 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(A, 0)];
word_type Y = SB[::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(B, 0)] ^
SB[256 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(B, 3)] ^
SB[512 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(B, 2)] ^
SB[768 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(B, 1)];

X += Y;
Y += X;

X += RK1;
Y += RK2;

C = policy_type::template rotr<1>(C ^ X);
D = policy_type::template rotl<1>(D) ^ Y;
}

inline static void tf_d(word_type A, word_type B, word_type &C, word_type &D, word_type RK1,
word_type RK2, const expanded_substitution_type &SB) {
word_type X = SB[::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(A, 3)] ^
SB[256 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(A, 2)] ^
SB[512 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(A, 1)] ^
SB[768 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(A, 0)];
word_type Y = SB[::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(B, 0)] ^
SB[256 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(B, 3)] ^
SB[512 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(B, 2)] ^
SB[768 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(B, 1)];

X += Y;
Y += X;

X += RK1;
Y += RK2;

C = policy_type::template rotl<1>(C) ^ X;
D = policy_type::template rotr<1>(D ^ Y);
}
};
} // namespace detail
} // namespace block
} // namespace crypto3
} // namespace nil

#endif // CRYPTO3_MISTY1_FUNCTIONS_CPP_HPP
184 changes: 184 additions & 0 deletions include/nil/crypto3/block/detail/twofish/twofish_policy.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
//---------------------------------------------------------------------------//
// Copyright (c) 2018-2020 Mikhail Komarov <nemo@nil.foundation>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//---------------------------------------------------------------------------//

#ifndef CRYPTO3_TWOFISH_POLICY_HPP
#define CRYPTO3_TWOFISH_POLICY_HPP

#include <nil/crypto3/block/detail/twofish/twofish_functions.hpp>

namespace nil {
namespace crypto3 {
namespace block {
namespace detail {
template<std::size_t KeyBits>
struct twofish_policy : public twofish_functions<KeyBits> { };

template<>
struct twofish_policy<128> : public twofish_functions<128> {
inline void static schedule_key(const key_type &key,
expanded_substitution_type &expanded_substitution,
key_schedule_type &round_key) {
std::array<byte_type, 16> S = {0};

for (size_t i = 0; i != key.size(); ++i) {
/*
* Do one column of the RS matrix multiplication
*/
if (key[i]) {
byte_type X = poly_to_exp[key[i] - 1];

byte_type RS1 = round_substitution[(4 * i) % 32];
byte_type RS2 = round_substitution[(4 * i + 1) % 32];
byte_type RS3 = round_substitution[(4 * i + 2) % 32];
byte_type RS4 = round_substitution[(4 * i + 3) % 32];

S[4 * (i / 8)] ^= exp_to_poly[(X + poly_to_exp[RS1 - 1]) % 255];
S[4 * (i / 8) + 1] ^= exp_to_poly[(X + poly_to_exp[RS2 - 1]) % 255];
S[4 * (i / 8) + 2] ^= exp_to_poly[(X + poly_to_exp[RS3 - 1]) % 255];
S[4 * (i / 8) + 3] ^= exp_to_poly[(X + poly_to_exp[RS4 - 1]) % 255];
}
}

for (size_t i = 0; i != key_schedule_size / 4; ++i) {
expanded_substitution[i] = mds0[q0[q0[i] ^ S[0]] ^ S[4]];
expanded_substitution[256 + i] = mds1[q0[q1[i] ^ S[1]] ^ S[5]];
expanded_substitution[512 + i] = mds2[q1[q0[i] ^ S[2]] ^ S[6]];
expanded_substitution[768 + i] = mds3[q1[q1[i] ^ S[3]] ^ S[7]];
}

for (size_t i = 0; i < expanded_substitution_size; i += 2) {
word_type X = mds0[q0[q0[i] ^ key[8]] ^ key[0]] ^ mds1[q0[q1[i] ^ key[9]] ^ key[1]] ^
mds2[q1[q0[i] ^ key[10]] ^ key[2]] ^ mds3[q1[q1[i] ^ key[11]] ^ key[3]];
word_type Y =
mds0[q0[q0[i + 1] ^ key[12]] ^ key[4]] ^ mds1[q0[q1[i + 1] ^ key[13]] ^ key[5]] ^
mds2[q1[q0[i + 1] ^ key[14]] ^ key[6]] ^ mds3[q1[q1[i + 1] ^ key[15]] ^ key[7]];
Y = policy_type::template rotl<8>(Y);
X += Y;
Y += X;

round_key[i] = X;
round_key[i + 1] = policy_type::template rotl<9>(Y);
}

S.fill(0);
}
};

template<>
struct twofish_policy<192> : public twofish_functions<192> {
inline void static schedule_key(const key_type &key,
expanded_substitution_type &expanded_substitution,
key_schedule_type &round_key) {
std::array<byte_type, 16> S = {0};

for (size_t i = 0; i != key.size(); ++i) {
/*
* Do one column of the RS matrix multiplication
*/
if (key[i]) {
byte_type X = poly_to_exp[key[i] - 1];

byte_type RS1 = round_substitution[(4 * i) % 32];
byte_type RS2 = round_substitution[(4 * i + 1) % 32];
byte_type RS3 = round_substitution[(4 * i + 2) % 32];
byte_type RS4 = round_substitution[(4 * i + 3) % 32];

S[4 * (i / 8)] ^= exp_to_poly[(X + poly_to_exp[RS1 - 1]) % 255];
S[4 * (i / 8) + 1] ^= exp_to_poly[(X + poly_to_exp[RS2 - 1]) % 255];
S[4 * (i / 8) + 2] ^= exp_to_poly[(X + poly_to_exp[RS3 - 1]) % 255];
S[4 * (i / 8) + 3] ^= exp_to_poly[(X + poly_to_exp[RS4 - 1]) % 255];
}
}

for (size_t i = 0; i != key_schedule_size / 4; ++i) {
expanded_substitution[i] = mds0[q0[q0[q1[i] ^ S[0]] ^ S[4]] ^ S[8]];
expanded_substitution[256 + i] = mds1[q0[q1[q1[i] ^ S[1]] ^ S[5]] ^ S[9]];
expanded_substitution[512 + i] = mds2[q1[q0[q0[i] ^ S[2]] ^ S[6]] ^ S[10]];
expanded_substitution[768 + i] = mds3[q1[q1[q0[i] ^ S[3]] ^ S[7]] ^ S[11]];
}

for (size_t i = 0; i < expanded_substitution_size; i += 2) {
word_type X = mds0[q0[q0[q1[i] ^ key[16]] ^ key[8]] ^ key[0]] ^
mds1[q0[q1[q1[i] ^ key[17]] ^ key[9]] ^ key[1]] ^
mds2[q1[q0[q0[i] ^ key[18]] ^ key[10]] ^ key[2]] ^
mds3[q1[q1[q0[i] ^ key[19]] ^ key[11]] ^ key[3]];
word_type Y = mds0[q0[q0[q1[i + 1] ^ key[20]] ^ key[12]] ^ key[4]] ^
mds1[q0[q1[q1[i + 1] ^ key[21]] ^ key[13]] ^ key[5]] ^
mds2[q1[q0[q0[i + 1] ^ key[22]] ^ key[14]] ^ key[6]] ^
mds3[q1[q1[q0[i + 1] ^ key[23]] ^ key[15]] ^ key[7]];
Y = policy_type::template rotl<8>(Y);
X += Y;
Y += X;

round_key[i] = X;
round_key[i + 1] = policy_type::template rotl<9>(Y);
}

S.fill(0);
}
};

template<>
struct twofish_policy<256> : public twofish_functions<256> {
inline static void schedule_key(const key_type &key,
expanded_substitution_type &expanded_substitution,
key_schedule_type &round_key) {
std::array<byte_type, 16> S = {0};

for (size_t i = 0; i != key.size(); ++i) {
/*
* Do one column of the RS matrix multiplication
*/
if (key[i]) {
byte_type X = poly_to_exp[key[i] - 1];

byte_type RS1 = round_substitution[(4 * i) % 32];
byte_type RS2 = round_substitution[(4 * i + 1) % 32];
byte_type RS3 = round_substitution[(4 * i + 2) % 32];
byte_type RS4 = round_substitution[(4 * i + 3) % 32];

S[4 * (i / 8)] ^= exp_to_poly[(X + poly_to_exp[RS1 - 1]) % 255];
S[4 * (i / 8) + 1] ^= exp_to_poly[(X + poly_to_exp[RS2 - 1]) % 255];
S[4 * (i / 8) + 2] ^= exp_to_poly[(X + poly_to_exp[RS3 - 1]) % 255];
S[4 * (i / 8) + 3] ^= exp_to_poly[(X + poly_to_exp[RS4 - 1]) % 255];
}
}

for (size_t i = 0; i != key_schedule_size / 4; ++i) {
expanded_substitution[i] = mds0[q0[q0[q1[q1[i] ^ S[0]] ^ S[4]] ^ S[8]] ^ S[12]];
expanded_substitution[256 + i] = mds1[q0[q1[q1[q0[i] ^ S[1]] ^ S[5]] ^ S[9]] ^ S[13]];
expanded_substitution[512 + i] = mds2[q1[q0[q0[q0[i] ^ S[2]] ^ S[6]] ^ S[10]] ^ S[14]];
expanded_substitution[768 + i] = mds3[q1[q1[q0[q1[i] ^ S[3]] ^ S[7]] ^ S[11]] ^ S[15]];
}

for (size_t i = 0; i < expanded_substitution_size; i += 2) {
word_type X = mds0[q0[q0[q1[q1[i] ^ key[24]] ^ key[16]] ^ key[8]] ^ key[0]] ^
mds1[q0[q1[q1[q0[i] ^ key[25]] ^ key[17]] ^ key[9]] ^ key[1]] ^
mds2[q1[q0[q0[q0[i] ^ key[26]] ^ key[18]] ^ key[10]] ^ key[2]] ^
mds3[q1[q1[q0[q1[i] ^ key[27]] ^ key[19]] ^ key[11]] ^ key[3]];
word_type Y = mds0[q0[q0[q1[q1[i + 1] ^ key[28]] ^ key[20]] ^ key[12]] ^ key[4]] ^
mds1[q0[q1[q1[q0[i + 1] ^ key[29]] ^ key[21]] ^ key[13]] ^ key[5]] ^
mds2[q1[q0[q0[q0[i + 1] ^ key[30]] ^ key[22]] ^ key[14]] ^ key[6]] ^
mds3[q1[q1[q0[q1[i + 1] ^ key[31]] ^ key[23]] ^ key[15]] ^ key[7]];
Y = policy_type::template rotl<8>(Y);
X += Y;
Y += X;

round_key[i] = X;
round_key[i + 1] = policy_type::template rotl<9>(Y);
}

S.fill(0);
}
};
} // namespace detail
} // namespace block
} // namespace crypto3
} // namespace nil

#endif // CRYPTO3_TWOFISH_POLICY_HPP
Loading

0 comments on commit dcf7b8c

Please sign in to comment.