Document the new DPF surfaces in one command set, and test the field, half-tree, and multipoint edges.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ryan Henry 2026-09-24 23:18:10 -06:00
parent 0d8a5a8131
commit 0dff6df8ed
250 changed files with 12199 additions and 1981 deletions

View file

@ -37,7 +37,7 @@ namespace chacha_detail
inline constexpr std::uint32_t zero_nonce[3] = {0, 0, 0};
/// ASCII `"dpf-chacha-prg"` plus two zero bytes. Public second half of the key.
/// @brief ASCII `"dpf-chacha-prg"` plus two zero bytes. Public second half of the key.
inline constexpr std::uint8_t domain[16] = {
'd', 'p', 'f', '-', 'c', 'h', 'a', 'c',
'h', 'a', '-', 'p', 'r', 'g', 0, 0
@ -77,7 +77,10 @@ simde__m128i load_block(const std::uint8_t * p) noexcept
return out;
}
/// 128-bit seed in the low half, `domain` in the high half, both little-endian.
/// @brief 128-bit seed in the low half, `domain` in the high half, both little-endian.
/// @param seed the PRG seed
/// @param key the `key`
HEDLEY_NON_NULL(2)
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
void seed_key(simde__m128i seed, std::uint32_t key[8]) noexcept
@ -92,8 +95,9 @@ void seed_key(simde__m128i seed, std::uint32_t key[8]) noexcept
}
template <int N>
HEDLEY_ALWAYS_INLINE
HEDLEY_CONST
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
constexpr std::uint32_t rotl(std::uint32_t x) noexcept
{
static_assert(N > 0 && N < 32, "ChaCha rotation is between 1 and 31");
@ -112,8 +116,9 @@ void quarter(std::uint32_t & a, std::uint32_t & b,
}
template <int N>
HEDLEY_ALWAYS_INLINE
HEDLEY_CONST
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
simde__m128i rotl_epi32(simde__m128i v) noexcept
{
static_assert(N > 0 && N < 32, "ChaCha rotation is between 1 and 31");
@ -121,6 +126,7 @@ simde__m128i rotl_epi32(simde__m128i v) noexcept
simde_mm_srli_epi32(v, 32 - N));
}
HEDLEY_NON_NULL(1)
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
void quarter(simde__m128i x[], int a, int b, int c, int d) noexcept
@ -135,6 +141,7 @@ void quarter(simde__m128i x[], int a, int b, int c, int d) noexcept
x[b] = rotl_epi32<7>(simde_mm_xor_si128(x[b], x[c]));
}
HEDLEY_CONST
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
std::uint32_t epi32_lane(simde__m128i v, int lane) noexcept
@ -150,8 +157,21 @@ std::uint32_t epi32_lane(simde__m128i v, int lane) noexcept
return static_cast<std::uint32_t>(simde_mm_cvtsi128_si32(v));
}
/// One ChaCha block. `key` is 8 little-endian words. `nonce` is 3 words.
/// @name ChaCha blocks
/// @tparam Rounds ChaCha round count. Must be positive and even
/// @param key the ChaCha key words
/// @param counter the ChaCha block counter
/// @param out the output buffer
/// @{
/// @brief One ChaCha block.
/// @details `key` is 8 little-endian words. `nonce` is 3 words.
/// @param key the ChaCha key words
/// @param counter the ChaCha block counter
/// @param nonce the ChaCha nonce
/// @param out the output buffer
template <unsigned Rounds>
HEDLEY_NON_NULL(1, 3, 4)
HEDLEY_NO_THROW
void block(const std::uint32_t key[8], std::uint32_t counter,
const std::uint32_t nonce[3], std::uint8_t out[64]) noexcept
@ -187,9 +207,10 @@ HEDLEY_PRAGMA(GCC unroll 16)
}
}
/// Four independent ChaCha blocks. Lane `i` uses `key[i]` and `counter[i]`.
/// Nonce is zero. Each `out[i]` receives 64 bytes.
/// @brief Four independent ChaCha blocks.
/// @details Lane `i` uses `key[i]` and `counter[i]`. Nonce is zero. Each `out[i]` receives 64 bytes.
template <unsigned Rounds>
HEDLEY_NON_NULL(1, 2, 3)
HEDLEY_NO_THROW
void block4(const std::uint32_t key[][8], const std::uint32_t counter[4],
std::uint8_t out[][64]) noexcept
@ -248,9 +269,12 @@ HEDLEY_PRAGMA(GCC unroll 16)
}
}
/// @}
} // namespace chacha_detail
/// ChaCha stream PRG with `Rounds` rounds (20 is RFC 8439).
/// @brief ChaCha stream PRG with `Rounds` rounds (20 is RFC 8439).
/// @tparam Rounds ChaCha round count. Must be positive and even
template <unsigned Rounds = 20>
struct chacha final
{
@ -272,7 +296,9 @@ struct chacha final
return chacha_detail::load_block(buf + 16 * (pos & 3u));
}
/// Positions 0 and 1, one ChaCha block (the first 32 keystream bytes).
/// @brief Positions 0 and 1, one ChaCha block (the first 32 keystream bytes).
/// @param seed the PRG seed
/// @return Positions 0 and 1, one ChaCha block (the first 32 keystream bytes)
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
static auto eval01(block_type seed) noexcept
@ -290,6 +316,12 @@ HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
HEDLEY_PRAGMA(GCC diagnostic pop)
}
/// @brief `count` blocks starting at lane `pos`. `output` is unused when `count` is 0.
/// @param seed the PRG seed
/// @param output the destination. Unused when `count` is 0
/// @param count the number of blocks
/// @param pos the 0-based index
/// @throws std::invalid_argument if `pos + count` wraps `uint32_t`.
HEDLEY_ALWAYS_INLINE
static void eval(block_type seed, block_type * HEDLEY_RESTRICT output,
psnip_uint32_t count, psnip_uint32_t pos = 0)
@ -436,19 +468,25 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
eval_x4(seeds + 4, output + 4, pos);
}
/// Raw-bit subtractive share of `T` for party `Party` (see `prg.hpp`).
/// @brief Raw-bit subtractive share of `T` for party `Party` (see `prg.hpp`).
/// @tparam T value type
/// @tparam Party party index, `0` or `1`
/// @param seed the PRG seed
/// @param pos the 0-based index
/// @return Raw-bit subtractive share of `T` for party `Party` (see `prg.hpp`)
/// @see `prg.hpp`
template <typename T, std::size_t Party>
HEDLEY_NO_THROW
static auto expand(block_type seed, psnip_uint32_t pos = 0) noexcept;
}; // struct chacha
/// RFC 8439 ChaCha20.
/// @brief RFC 8439 ChaCha20.
using chacha20 = chacha<20>;
/// ChaCha12. Same keying as `chacha20`, 12 rounds.
/// @brief ChaCha12. Same keying as `chacha20`, 12 rounds.
using chacha12 = chacha<12>;
/// ChaCha8. Same keying as `chacha20`, 8 rounds.
/// @brief ChaCha8. Same keying as `chacha20`, 8 rounds.
using chacha8 = chacha<8>;
} // namespace prg