Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,14 @@
# error No known always_inline attribute for this platform.
#endif

#define PRAGMA(x) _Pragma(#x)

#if defined(__clang__)
# define UNROLL_LOOP(N) PRAGMA(clang loop unroll_count(N))
#elif defined(__GNUC__)
# define UNROLL_LOOP(N) PRAGMA(GCC unroll N)
#else
# define UNROLL_LOOP(N)
#endif

#endif // BITCOIN_ATTRIBUTES_H
1 change: 1 addition & 0 deletions src/crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
add_library(bitcoin_crypto STATIC EXCLUDE_FROM_ALL
aes.cpp
chacha20.cpp
chacha20_vec_base.cpp
chacha20poly1305.cpp
hex_base.cpp
hkdf_sha256_32.cpp
Expand Down
36 changes: 31 additions & 5 deletions src/crypto/chacha20.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@

#include <crypto/common.h>
#include <crypto/chacha20.h>
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3c4a209:
direct

#include <crypto/chacha20_vec.h>
#include <support/cleanse.h>
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another direct


#include <algorithm>
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3c4a209:
yup, works correctly

#include <bit>
#include <cassert>
#include <limits>
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

direct comment from global


static_assert(ChaCha20Aligned::BLOCKLEN == CHACHA20_VEC_BLOCKLEN);

#define QUARTERROUND(a,b,c,d) \
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3c4a209:
pending 2

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3c4a209:
pending 2

a += b; d = std::rotl(d ^ a, 16); \
Expand Down Expand Up @@ -157,13 +161,14 @@ inline void ChaCha20Aligned::Keystream(std::span<std::byte> output) noexcept
}
}

inline void ChaCha20Aligned::Crypt(std::span<const std::byte> in_bytes, std::span<std::byte> out_bytes) noexcept
static inline void chacha20_crypt(std::span<const std::byte> in_bytes, std::span<std::byte> out_bytes, uint32_t input[12]) noexcept
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pending

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pending

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a535ff1:
commit hash added automatically

{
assert(in_bytes.size() == out_bytes.size());
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a535ff1:
pending

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a535ff1:
pending

const std::byte* m = in_bytes.data();
std::byte* c = out_bytes.data();
size_t blocks = out_bytes.size() / BLOCKLEN;
assert(blocks * BLOCKLEN == out_bytes.size());
size_t blocks = out_bytes.size() / ChaCha20Aligned::BLOCKLEN;
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

direct again

assert(blocks * ChaCha20Aligned::BLOCKLEN == out_bytes.size());


uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
uint32_t j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
Expand Down Expand Up @@ -273,8 +278,29 @@ inline void ChaCha20Aligned::Crypt(std::span<const std::byte> in_bytes, std::spa
return;
}
blocks -= 1;
c += BLOCKLEN;
m += BLOCKLEN;
c += ChaCha20Aligned::BLOCKLEN;
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m += ChaCha20Aligned::BLOCKLEN;
}
}


inline void ChaCha20Aligned::Crypt(std::span<const std::byte> in_bytes, std::span<std::byte> out_bytes) noexcept
{
assert(in_bytes.size() == out_bytes.size());
size_t blocks = out_bytes.size() / ChaCha20Aligned::BLOCKLEN;
assert(blocks * ChaCha20Aligned::BLOCKLEN == out_bytes.size());
#ifdef ENABLE_CHACHA20_VEC
// Only use the vectorized implementations if the counter will not overflow.
const bool overflow = static_cast<uint64_t>(input[8]) + blocks > std::numeric_limits<uint32_t>::max();
if (blocks > 1 && !overflow) {
const auto state = std::to_array(input);
chacha20_vec_base::chacha20_crypt_vectorized(in_bytes, out_bytes, state);
const size_t blocks_written = blocks - (out_bytes.size() / ChaCha20Aligned::BLOCKLEN);
input[8] += blocks_written;
}
#endif
if (in_bytes.size()) {
chacha20_crypt(in_bytes, out_bytes, input);
}
}

Expand Down
30 changes: 30 additions & 0 deletions src/crypto/chacha20_vec.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) 2025-present The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_CRYPTO_CHACHA20_VEC_H
#define BITCOIN_CRYPTO_CHACHA20_VEC_H

#include <array>
#include <cstdint>
#include <cstddef>
#include <span>

static constexpr size_t CHACHA20_VEC_BLOCKLEN = 64;

#ifdef __has_builtin
#if __has_builtin(__builtin_shufflevector)
#define ENABLE_CHACHA20_VEC 1
#endif
#endif

#ifdef ENABLE_CHACHA20_VEC

namespace chacha20_vec_base
{
void chacha20_crypt_vectorized(std::span<const std::byte>& in_bytes, std::span<std::byte>& out_bytes, const std::array<uint32_t, 12>& input) noexcept;
}

#endif // ENABLE_CHACHA20_VEC

#endif // BITCOIN_CRYPTO_CHACHA20_VEC_H
Loading
Loading