25 #ifndef CRYPTO3_RIJNDAEL_IMPL_HPP
26 #define CRYPTO3_RIJNDAEL_IMPL_HPP
30 #include <nil/crypto3/detail/stream_endian.hpp>
31 #include <nil/crypto3/detail/pack.hpp>
40 template<std::
size_t KeyBitsImpl, std::
size_t BlockBitsImpl,
typename PolicyType>
42 typedef PolicyType policy_type;
44 typedef typename policy_type::key_type key_type;
45 typedef typename policy_type::key_schedule_type key_schedule_type;
46 typedef typename policy_type::key_schedule_word_type key_schedule_word_type;
48 typedef typename policy_type::block_type block_type;
50 typedef typename policy_type::constants_type constants_type;
51 typedef typename policy_type::shift_offsets_type shift_offsets_type;
52 typedef typename policy_type::mm_type mm_type;
54 BOOST_STATIC_ASSERT(KeyBitsImpl == PolicyType::key_bits);
55 BOOST_STATIC_ASSERT(BlockBitsImpl == PolicyType::block_bits);
57 static inline key_schedule_word_type sub_word(
const key_schedule_word_type &x,
58 const constants_type &constants) {
59 key_schedule_word_type result = {0};
61 for (std::size_t i = 0; i < policy_type::word_bytes; ++i) {
63 result << CHAR_BIT | constants[::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(x, i)];
69 static inline void sub_bytes(block_type &state,
const constants_type &sbox) {
71 for (std::size_t i = 0; i < policy_type::word_bytes * policy_type::block_words; ++i) {
72 state[i] = sbox[state[i]];
76 static inline void shift_rows(block_type &state,
const shift_offsets_type &offset) {
77 std::array<typename policy_type::byte_type, policy_type::block_words> tmp = {0};
81 for (std::size_t row = 1; row < policy_type::word_bytes; ++row) {
82 const std::size_t off = offset[row - 1];
84 for (std::size_t i = 0; i < off; ++i) {
85 tmp[i] = state[i * policy_type::word_bytes + row];
88 for (std::size_t i = 0; i < policy_type::block_words - 1; ++i) {
89 state[i * policy_type::word_bytes + row] =
90 state[(i + off) * policy_type::word_bytes + row];
93 for (std::size_t i = 0; i < off; ++i) {
94 state[(policy_type::block_words - 1 - i) * policy_type::word_bytes + row] =
100 template<
typename StateType>
101 static inline block_type mix_columns(
const StateType &state,
const mm_type &mm) {
102 block_type tmp = {0};
105 for (std::size_t col = 0; col < policy_type::block_words; ++col) {
107 for (std::size_t row = 0; row < policy_type::word_bytes; ++row) {
109 for (std::size_t k = 0; k < policy_type::word_bytes; ++k) {
110 tmp[col * policy_type::word_bytes + row] ^=
111 policy_type::mul(mm[row * policy_type::word_bytes + k],
112 state[col * policy_type::word_bytes + k]);
120 template<
typename InputIterator>
121 static inline void add_round_key(block_type &state, InputIterator first, InputIterator last) {
122 BOOST_ASSERT(std::distance(first, last) == policy_type::block_words &&
123 state.size() == policy_type::block_bytes);
126 for (std::size_t i = 0; i < policy_type::block_words && first != last; ++i && ++first) {
128 for (std::size_t j = 0; j < policy_type::word_bytes; ++j) {
129 state[i * policy_type::word_bytes + j] ^=
130 ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(*first,
131 policy_type::word_bytes - (j + 1));
136 static inline void apply_round(std::uint8_t round, block_type &state,
const key_schedule_type &w,
137 const constants_type &sbox,
const shift_offsets_type &offsets,
139 sub_bytes(state, sbox);
140 shift_rows(state, offsets);
141 state = mix_columns(state, mm);
142 add_round_key(state, w.begin() + round * policy_type::block_words,
143 w.begin() + (round + 1) * policy_type::block_words);
147 static typename policy_type::block_type encrypt_block(
const block_type &plaintext,
148 const key_schedule_type &encryption_key) {
149 block_type state = plaintext;
151 add_round_key(state, encryption_key.begin(), encryption_key.begin() + policy_type::block_words);
154 for (std::size_t round = 1; round < policy_type::rounds; ++round) {
155 apply_round(round, state, encryption_key, policy_type::constants,
156 policy_type::shift_offsets, policy_type::mm);
159 sub_bytes(state, policy_type::constants);
160 shift_rows(state, policy_type::shift_offsets);
161 add_round_key(state, encryption_key.begin() + policy_type::rounds * policy_type::block_words,
162 encryption_key.begin() + (policy_type::rounds + 1) * policy_type::block_words);
167 static typename policy_type::block_type decrypt_block(
const block_type &plaintext,
168 const key_schedule_type &decryption_key) {
169 block_type state = plaintext;
171 add_round_key(state, decryption_key.begin() + policy_type::rounds * policy_type::block_words,
172 decryption_key.begin() + (policy_type::rounds + 1) * policy_type::block_words);
175 for (std::size_t round = policy_type::rounds - 1; round > 0; --round) {
176 apply_round(round, state, decryption_key, policy_type::inverted_constants,
177 policy_type::inverted_shift_offsets, policy_type::inverted_mm);
180 sub_bytes(state, policy_type::inverted_constants);
181 shift_rows(state, policy_type::inverted_shift_offsets);
182 add_round_key(state, decryption_key.begin(), decryption_key.begin() + policy_type::block_words);
187 static void schedule_key(
const key_type &key, key_schedule_type &encryption_key,
188 key_schedule_type &decryption_key) {
192 policy_type::word_bits>(
193 key.begin(), key.begin() + policy_type::key_words * policy_type::word_bytes,
194 encryption_key.begin());
197 for (std::size_t i = policy_type::key_words; i < policy_type::key_schedule_words; ++i) {
198 typename policy_type::key_schedule_word_type tmp = encryption_key[i - 1];
199 if (i % policy_type::key_words == 0) {
200 tmp = sub_word(policy_type::rotate_left(tmp), policy_type::constants) ^
201 policy_type::round_constants[i / policy_type::key_words - 1];
202 }
else if (policy_type::key_words > 6 && i % policy_type::key_words == 4) {
203 tmp = sub_word(tmp, policy_type::constants);
205 encryption_key[i] = encryption_key[i - policy_type::key_words] ^ tmp;
208 std::array<typename policy_type::byte_type, policy_type::key_schedule_bytes> bekey = {0};
211 CHAR_BIT>(encryption_key.begin(), encryption_key.end(),
215 for (std::uint8_t round = 1; round < policy_type::rounds; ++round) {
217 (round + 1) * policy_type::block_bytes),
218 policy_type::inverted_mm),
219 bekey.begin() + round * policy_type::block_bytes);
224 policy_type::word_bits>(bekey.begin(), bekey.end(),
225 decryption_key.begin());
void pack(InputIterator first, InputIterator last, std::random_access_iterator_tag, OutputIterator out)
Packs elements from the range [first, last) into elements starting from out. Works for input containe...
Definition: block/include/nil/crypto3/detail/pack.hpp:835
constexpr vector< T, M > slice(vector< T, N > v, std::size_t start=0)
slices a vector into a subvector
Definition: vector/utility.hpp:170
OutputIterator move(const SinglePassRange &rng, OutputIterator result)
Definition: move.hpp:45
little_unit_big_bit< 8 > little_octet_big_bit
Definition: algebra/include/nil/crypto3/detail/stream_endian.hpp:65
big_unit_big_bit< 8 > big_octet_big_bit
Definition: algebra/include/nil/crypto3/detail/stream_endian.hpp:55