myl7/fss 2.0.0
Function secret sharing (FSS) primitives including distributed point/comparison function (DPF/DCF)
Loading...
Searching...
No Matches
chacha.cuh
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
7
8#pragma once
9#include <fss/prg.cuh>
10#include <cuda_runtime.h>
11#include <cuda/std/array>
12#include <fss/util.cuh>
13
14namespace fss::prg {
15
24template <int mul, int rounds = 20>
25 requires(rounds > 0 && rounds % 2 == 0 && (mul == 1 || mul == 2 || mul == 4))
26class ChaCha {
27public:
35 __host__ __device__ ChaCha(int nonce0, int nonce1) : nonce_{nonce0, nonce1} {}
36
37 __host__ __device__ cuda::std::array<int4, mul> Gen(int4 seed);
38
39private:
40 int nonce_[2];
41
42 template <int n>
43 __host__ __device__ static int RotateLeft(int a);
44
45 __host__ __device__ static void QuarterRound(int &a, int &b, int &c, int &d);
46
47 __host__ __device__ static void Rounds(int4 x[4]);
48
49 __host__ __device__ static void ExpandKey(int4 x[4]);
50
51 // The nothing-up-my-sleeve constant for 32B key: "expand 32-byte k"
52 constexpr static int4 kConstant32 = {
53 0x61707865, // "expa"
54 0x3320646e, // "nd 3"
55 0x79622d32, // "2-by"
56 0x6b206574, // "te k"
57 };
58 // The nothing-up-my-sleeve constant for 16B key: "expand 16-byte k"
59 constexpr static int4 kConstant16 = {
60 0x61707865, // "expa"
61 0x3120646e, // "nd 1"
62 0x79622d36, // "6-by"
63 0x6b206574, // "te k"
64 };
65};
66// -----------------------------------------------------------------------------
67
68template <int mul, int rounds>
69 requires(rounds > 0 && rounds % 2 == 0 && (mul == 1 || mul == 2 || mul == 4))
70template <int n>
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)));
74}
75
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));
80 d ^= a;
81 d = RotateLeft<16>(d);
82 c = static_cast<int>(static_cast<uint32_t>(c) + static_cast<uint32_t>(d));
83 b ^= c;
84 b = RotateLeft<12>(b);
85 a = static_cast<int>(static_cast<uint32_t>(a) + static_cast<uint32_t>(b));
86 d ^= a;
87 d = RotateLeft<8>(d);
88 c = static_cast<int>(static_cast<uint32_t>(c) + static_cast<uint32_t>(d));
89 b ^= c;
90 b = RotateLeft<7>(b);
91}
92
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) {
97 // Column rounds
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);
102 // Diagonal rounds
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);
107 }
108}
109
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]) {
113 x[2] = x[1];
114}
115
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) {
119 int4 buf[4];
120
121 // Constant
122 if constexpr (mul <= 2) buf[0] = kConstant16;
123 else buf[0] = kConstant32;
124
125 // Key from the seed
126 buf[1] = seed;
127 ExpandKey(buf);
128
129 // Counter is always 0 because we only gen one block
130 buf[3].x = 0;
131 buf[3].y = 0;
132 // Nonce
133 buf[3].z = nonce_[0];
134 buf[3].w = nonce_[1];
135
136 Rounds(buf);
137
138 buf[1] = util::Xor(buf[1], seed);
139 if constexpr (mul == 1) {
140 return {buf[1]};
141 } else if constexpr (mul == 2) {
142 buf[0] = util::Xor(buf[0], kConstant16);
143 return {buf[0], buf[1]};
144 } else {
145 buf[0] = util::Xor(buf[0], kConstant32);
146 buf[2] = util::Xor(buf[2], seed);
147 buf[3] = util::Xor(buf[3], {0, 0, nonce_[0], nonce_[1]});
148 return {buf[0], buf[1], buf[2], buf[3]};
149 }
150}
151
152static_assert(Prgable<ChaCha<1>, 1> && Prgable<ChaCha<2>, 2> && Prgable<ChaCha<4>, 4>);
153
154} // namespace fss::prg
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