Skip to content

Commit

Permalink
Optimize XTS tweak computation
Browse files Browse the repository at this point in the history
For AES-128 with AES-NI this almost doubles performance. The
benefit for slower ciphers is less pronounced.
  • Loading branch information
randombit committed May 13, 2024
1 parent 7606d70 commit 131c214
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 6 deletions.
4 changes: 1 addition & 3 deletions src/lib/modes/xts/xts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,7 @@ void XTS_Mode::update_tweak(size_t which) {

const size_t blocks_in_tweak = tweak_blocks();

for(size_t i = 1; i < blocks_in_tweak; ++i) {
poly_double_n_le(&m_tweak[i * BS], &m_tweak[(i - 1) * BS], BS);
}
xts_update_tweak_block(m_tweak.data(), BS, blocks_in_tweak);
}

size_t XTS_Encryption::output_length(size_t input_length) const {
Expand Down
6 changes: 3 additions & 3 deletions src/lib/utils/loadstor.h
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ inline constexpr auto store_be(ParamTs&&... params) {
namespace detail {

template <Endianness endianness, unsigned_integralish T>
size_t copy_out_any_word_aligned_portion(std::span<uint8_t>& out, std::span<const T>& in) {
inline size_t copy_out_any_word_aligned_portion(std::span<uint8_t>& out, std::span<const T>& in) {
const size_t full_words = out.size() / sizeof(T);
const size_t full_word_bytes = full_words * sizeof(T);
const size_t remaining_bytes = out.size() - full_word_bytes;
Expand All @@ -732,7 +732,7 @@ size_t copy_out_any_word_aligned_portion(std::span<uint8_t>& out, std::span<cons
* byte order.
*/
template <ranges::spanable_range InR>
void copy_out_be(std::span<uint8_t> out, InR&& in) {
inline void copy_out_be(std::span<uint8_t> out, InR&& in) {
using T = std::ranges::range_value_t<InR>;
std::span<const T> in_s{in};
const auto remaining_bytes = detail::copy_out_any_word_aligned_portion<detail::Endianness::Big>(out, in_s);
Expand All @@ -748,7 +748,7 @@ void copy_out_be(std::span<uint8_t> out, InR&& in) {
* byte order.
*/
template <ranges::spanable_range InR>
void copy_out_le(std::span<uint8_t> out, InR&& in) {
inline void copy_out_le(std::span<uint8_t> out, InR&& in) {
using T = std::ranges::range_value_t<InR>;
std::span<const T> in_s{in};
const auto remaining_bytes = detail::copy_out_any_word_aligned_portion<detail::Endianness::Little>(out, in_s);
Expand Down
24 changes: 24 additions & 0 deletions src/lib/utils/poly_dbl/poly_dbl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,28 @@ void poly_double_n_le(uint8_t out[], const uint8_t in[], size_t n) {
}
}

void xts_update_tweak_block(uint8_t tweak[], size_t BS, size_t blocks_in_tweak) {
if(BS == 16) {
constexpr size_t LIMBS = 2;

uint64_t W[LIMBS];
load_le(W, &tweak[0], LIMBS);

const uint64_t POLY = static_cast<uint64_t>(MinWeightPolynomial::P128);

for(size_t i = 1; i < blocks_in_tweak; ++i) {
const uint64_t carry = POLY * (W[1] >> 63);
W[1] = (W[1] << 1) ^ (W[0] >> 63);
W[0] = (W[0] << 1) ^ carry;
copy_out_le(std::span(&tweak[i * BS], 2 * 8), W);
}
} else {
for(size_t i = 1; i < blocks_in_tweak; ++i) {
const uint8_t* prev = &tweak[(i - 1) * BS];
uint8_t* cur = &tweak[i * BS];
poly_double_n_le(cur, prev, BS);
}
}
}

} // namespace Botan
5 changes: 5 additions & 0 deletions src/lib/utils/poly_dbl/poly_dbl.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ inline void poly_double_n(uint8_t buf[], size_t n) {
*/
void BOTAN_TEST_API poly_double_n_le(uint8_t out[], const uint8_t in[], size_t n);

/*
* Tweak block update step for XTS
*/
void xts_update_tweak_block(uint8_t tweak[], size_t BS, size_t n);

} // namespace Botan

#endif

0 comments on commit 131c214

Please sign in to comment.