10#include <cuda_runtime.h>
11#include <cuda/std/array>
24template <
int mul,
int rounds = 20>
25 requires(rounds > 0 && rounds % 2 == 0 && (mul == 1 || mul == 2 || mul == 4))
35 __host__ __device__
ChaCha(
int nonce0,
int nonce1) : nonce_{nonce0, nonce1} {}
37 __host__ __device__ cuda::std::array<int4, mul> Gen(int4 seed);
43 __host__ __device__
static int RotateLeft(
int a);
45 __host__ __device__
static void QuarterRound(
int &a,
int &b,
int &c,
int &d);
47 __host__ __device__
static void Rounds(int4 x[4]);
49 __host__ __device__
static void ExpandKey(int4 x[4]);
52 constexpr static int4 kConstant32 = {
59 constexpr static int4 kConstant16 = {
68template <
int mul,
int rounds>
69 requires(rounds > 0 && rounds % 2 == 0 && (mul == 1 || mul == 2 || mul == 4))
71__host__ __device__
inline int ChaCha<mul, rounds>::RotateLeft(
int a) {
72 auto u =
static_cast<unsigned>(a);
73 return static_cast<int>((u << n) | (u >> (32 - n)));
76template <
int mul,
int rounds>
77 requires(rounds > 0 && rounds % 2 == 0 && (mul == 1 || mul == 2 || mul == 4))
78__host__ __device__
inline void ChaCha<mul, rounds>::QuarterRound(
int &a,
int &b,
int &c,
int &d) {
79 a =
static_cast<int>(
static_cast<uint32_t
>(a) +
static_cast<uint32_t
>(b));
81 d = RotateLeft<16>(d);
82 c =
static_cast<int>(
static_cast<uint32_t
>(c) +
static_cast<uint32_t
>(d));
84 b = RotateLeft<12>(b);
85 a =
static_cast<int>(
static_cast<uint32_t
>(a) +
static_cast<uint32_t
>(b));
88 c =
static_cast<int>(
static_cast<uint32_t
>(c) +
static_cast<uint32_t
>(d));
93template <
int mul,
int rounds>
94 requires(rounds > 0 && rounds % 2 == 0 && (mul == 1 || mul == 2 || mul == 4))
95__host__ __device__
inline void ChaCha<mul, rounds>::Rounds(int4 x[4]) {
96 for (
int i = 0; i < rounds; i += 2) {
98 QuarterRound(x[0].x, x[1].x, x[2].x, x[3].x);
99 QuarterRound(x[0].y, x[1].y, x[2].y, x[3].y);
100 QuarterRound(x[0].z, x[1].z, x[2].z, x[3].z);
101 QuarterRound(x[0].w, x[1].w, x[2].w, x[3].w);
103 QuarterRound(x[0].x, x[1].y, x[2].z, x[3].w);
104 QuarterRound(x[0].y, x[1].z, x[2].w, x[3].x);
105 QuarterRound(x[0].z, x[1].w, x[2].x, x[3].y);
106 QuarterRound(x[0].w, x[1].x, x[2].y, x[3].z);
110template <
int mul,
int rounds>
111 requires(rounds > 0 && rounds % 2 == 0 && (mul == 1 || mul == 2 || mul == 4))
112__host__ __device__
inline void ChaCha<mul, rounds>::ExpandKey(int4 x[4]) {
116template <
int mul,
int rounds>
117 requires(rounds > 0 && rounds % 2 == 0 && (mul == 1 || mul == 2 || mul == 4))
118__host__ __device__
inline cuda::std::array<int4, mul> ChaCha<mul, rounds>::Gen(int4 seed) {
122 if constexpr (mul <= 2) buf[0] = kConstant16;
123 else buf[0] = kConstant32;
133 buf[3].z = nonce_[0];
134 buf[3].w = nonce_[1];
139 if constexpr (mul == 1) {
141 }
else if constexpr (mul == 2) {
143 return {buf[0], buf[1]};
147 buf[3] =
util::Xor(buf[3], {0, 0, nonce_[0], nonce_[1]});
148 return {buf[0], buf[1], buf[2], buf[3]};
152static_assert(Prgable<ChaCha<1>, 1> && Prgable<ChaCha<2>, 2> && Prgable<ChaCha<4>, 4>);
ChaCha(int nonce0, int nonce1)
Constructor.
Definition chacha.cuh:35
int4 Xor(int4 lhs, int4 rhs)
Return the bitwise XOR of two 128-bit blocks.
Definition util.cuh:29