Skip to content

Commit 6972662

Browse files
committed
Add fuzzing harness to compare python and cpp chacha20 outputs
This behaves like the client and sends requests to the python server file (src/test/fuzz/script.py) to perform certain operations, receives python output computed in the server file and compares both to see if they match.
1 parent 51c090a commit 6972662

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

src/Makefile.test.include

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ test_fuzz_fuzz_SOURCES = \
240240
test/fuzz/crypto_chacha20_poly1305_aead.cpp \
241241
test/fuzz/crypto_common.cpp \
242242
test/fuzz/crypto_diff_fuzz_chacha20.cpp \
243+
test/fuzz/crypto_diff_fuzz_pychacha20.cpp \
243244
test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp \
244245
test/fuzz/crypto_poly1305.cpp \
245246
test/fuzz/cuckoocache.cpp \

src/test/fuzz/crypto_diff_fuzz_pychacha20.cpp

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5+
#include <crypto/chacha20.h>
6+
#include <test/fuzz/FuzzedDataProvider.h>
7+
#include <test/fuzz/fuzz.h>
8+
#include <test/fuzz/util.h>
9+
510
#include <cstdint>
611
#include <netdb.h>
712
#include <netinet/in.h>
@@ -12,6 +17,8 @@
1217
#include <unistd.h>
1318
#include <vector>
1419

20+
#define SV_SOCK_PATH "/tmp/socket_test.s"
21+
1522
// read size from a file descriptor
1623
// return true if val is set, false for EOF
1724
static bool read_uint32(int read_fd, uint32_t& val)
@@ -128,4 +135,84 @@ void send_to_python(int sockfd, uint32_t num)
128135
iBuf += rc;
129136
}
130137
}
138+
}
139+
140+
FUZZ_TARGET(crypto_diff_fuzz_pychacha20)
141+
{
142+
/* ----------------------- socket initialisation -------------------------- */
143+
struct sockaddr_un addr;
144+
145+
// Create a new client socket with domain: AF_UNIX, type: SOCK_STREAM, protocol: 0
146+
int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
147+
148+
// Make sure socket's file descriptor is legit.
149+
if (sockfd == -1) {
150+
std::cout << "socket creation failed...\n";
151+
exit(1);
152+
}
153+
154+
// Construct server address, and make the connection.
155+
memset(&addr, 0, sizeof(struct sockaddr_un));
156+
addr.sun_family = AF_UNIX;
157+
strncpy(addr.sun_path, SV_SOCK_PATH, sizeof(addr.sun_path) - 1);
158+
159+
struct timeval tv;
160+
tv.tv_sec = 60;
161+
tv.tv_usec = 0;
162+
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
163+
164+
// Connects the active socket(sockfd) to the listening socket whose address is addr.
165+
if (connect(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_un)) == -1) {
166+
std::cout << "connection with the server failed...\n";
167+
exit(1);
168+
}
169+
/* ----------------------- initialisation over ----------------------- */
170+
/* ----------------------- fuzzing phase ------------------------------ */
171+
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
172+
ChaCha20 chacha20;
173+
174+
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32);
175+
chacha20 = ChaCha20{key.data(), key.size()};
176+
// send to python server [4][init][key.size][key.data]
177+
send_to_python(sockfd, "init");
178+
send_to_python(sockfd, std::string(key.begin(), key.end()));
179+
// check if response from python server is "ok"
180+
std::vector<unsigned char> response = read_from_python(sockfd);
181+
std::string s1(response.begin(), response.end());
182+
assert(s1 == "ok");
183+
184+
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 3000)
185+
{
186+
CallOneOf(
187+
fuzzed_data_provider,
188+
[&] {
189+
uint32_t integralInRange = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096);
190+
std::vector<uint8_t> cpp_keystream(integralInRange);
191+
chacha20.Keystream(cpp_keystream.data(), cpp_keystream.size());
192+
// send to python server [6]["stream"][keystream_size]
193+
send_to_python(sockfd, "stream");
194+
send_to_python(sockfd, integralInRange);
195+
// check if the cpp and python computations of the keystream match
196+
std::vector<unsigned char> py_keystream = read_from_python(sockfd);
197+
assert(cpp_keystream == py_keystream);
198+
},
199+
[&] {
200+
uint32_t integralInRange = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096);
201+
std::vector<uint8_t> cpp_ciphertext(integralInRange);
202+
const std::vector<uint8_t> plaintext = ConsumeFixedLengthByteVector(fuzzed_data_provider, integralInRange);
203+
chacha20.Crypt(plaintext.data(), cpp_ciphertext.data(), integralInRange);
204+
// send to python server [5]["crypt"][size][plaintext]
205+
send_to_python(sockfd, "crypt");
206+
send_to_python(sockfd, std::string(plaintext.begin(), plaintext.end()));
207+
// check if the cpp and python ciphertext match
208+
std::vector<unsigned char> py_ciphertext = read_from_python(sockfd);
209+
assert(cpp_ciphertext == py_ciphertext);
210+
});
211+
}
212+
send_to_python(sockfd, "exit");
213+
response = read_from_python(sockfd);
214+
std::string s2(response.begin(), response.end());
215+
assert(s2 == "ok");
216+
/* ----------------------- end fuzzing phase ----------------------- */
217+
close(sockfd);
131218
}

0 commit comments

Comments
 (0)