diff --git a/contrib/fuzz_testing/fuzz.sh b/contrib/fuzz_testing/fuzz.sh index 5c88c3727..065dcc381 100755 --- a/contrib/fuzz_testing/fuzz.sh +++ b/contrib/fuzz_testing/fuzz.sh @@ -10,12 +10,12 @@ fi type="$1" if test -z "$type" then - echo "usage: $0 block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin|bulletproof" + echo "usage: $0 block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin|bulletproof|utf8|clsag|clsag_cout|clsag_message|clsag_pubs" exit 1 fi case "$type" in - block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin|bulletproof|utf8) ;; - *) echo "usage: $0 block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin|bulletproof|utf8"; exit 1 ;; + block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin|bulletproof|utf8|clsag|clsag_cout|clsag_message|clsag_pubs) ;; + *) echo "usage: $0 block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin|bulletproof|utf8|clsag|clsag_cout|clsag_message|clsag_pubs"; exit 1 ;; esac if test -d "fuzz-out/$type" diff --git a/tests/data/fuzz/clsag/clsag0 b/tests/data/fuzz/clsag/clsag0 new file mode 100644 index 000000000..e69de29bb diff --git a/tests/data/fuzz/clsag/clsag1 b/tests/data/fuzz/clsag/clsag1 new file mode 100644 index 000000000..36205eed5 Binary files /dev/null and b/tests/data/fuzz/clsag/clsag1 differ diff --git a/tests/data/fuzz/clsag_cout/clsag0 b/tests/data/fuzz/clsag_cout/clsag0 new file mode 100644 index 000000000..e69de29bb diff --git a/tests/data/fuzz/clsag_cout/clsag1 b/tests/data/fuzz/clsag_cout/clsag1 new file mode 100644 index 000000000..31cc17d65 --- /dev/null +++ b/tests/data/fuzz/clsag_cout/clsag1 @@ -0,0 +1 @@ +7kq>}`΄j@#]d| 5n \ No newline at end of file diff --git a/tests/data/fuzz/clsag_message/clsag0 b/tests/data/fuzz/clsag_message/clsag0 new file mode 100644 index 000000000..e69de29bb diff --git a/tests/data/fuzz/clsag_message/clsag1 b/tests/data/fuzz/clsag_message/clsag1 new file mode 100644 index 000000000..9870828e3 Binary files /dev/null and b/tests/data/fuzz/clsag_message/clsag1 differ diff --git a/tests/data/fuzz/clsag_pubs/clsag0 b/tests/data/fuzz/clsag_pubs/clsag0 new file mode 100644 index 000000000..e69de29bb diff --git a/tests/data/fuzz/clsag_pubs/clsag1 b/tests/data/fuzz/clsag_pubs/clsag1 new file mode 100644 index 000000000..15515fe3f Binary files /dev/null and b/tests/data/fuzz/clsag_pubs/clsag1 differ diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt index 3b8ae9e7d..5d14c51cc 100644 --- a/tests/fuzz/CMakeLists.txt +++ b/tests/fuzz/CMakeLists.txt @@ -294,3 +294,51 @@ target_link_libraries(utf8_fuzz_tests ${CMAKE_THREAD_LIBS_INIT} ${EXTRA_LIBRARIES} $ENV{LIB_FUZZING_ENGINE}) + +monero_add_minimal_executable(clsag_fuzz_tests clsag.cpp clsag_init.h fuzzer.cpp) +target_link_libraries(clsag_fuzz_tests + PRIVATE + cryptonote_core + serialization + ${CMAKE_THREAD_LIBS_INIT} + ${EXTRA_LIBRARIES} + $ENV{LIB_FUZZING_ENGINE}) +set_property(TARGET clsag_fuzz_tests + PROPERTY + FOLDER "tests") + +monero_add_minimal_executable(clsag_cout_fuzz_tests clsag_cout.cpp clsag_init.h fuzzer.cpp) +target_link_libraries(clsag_cout_fuzz_tests + PRIVATE + cryptonote_core + serialization + ${CMAKE_THREAD_LIBS_INIT} + ${EXTRA_LIBRARIES} + $ENV{LIB_FUZZING_ENGINE}) +set_property(TARGET clsag_cout_fuzz_tests + PROPERTY + FOLDER "tests") + +monero_add_minimal_executable(clsag_message_fuzz_tests clsag_message.cpp clsag_init.h fuzzer.cpp) +target_link_libraries(clsag_message_fuzz_tests + PRIVATE + cryptonote_core + serialization + ${CMAKE_THREAD_LIBS_INIT} + ${EXTRA_LIBRARIES} + $ENV{LIB_FUZZING_ENGINE}) +set_property(TARGET clsag_message_fuzz_tests + PROPERTY + FOLDER "tests") + +monero_add_minimal_executable(clsag_pubs_fuzz_tests clsag_pubs.cpp clsag_init.h fuzzer.cpp) +target_link_libraries(clsag_pubs_fuzz_tests + PRIVATE + cryptonote_core + serialization + ${CMAKE_THREAD_LIBS_INIT} + ${EXTRA_LIBRARIES} + $ENV{LIB_FUZZING_ENGINE}) +set_property(TARGET clsag_pubs_fuzz_tests + PROPERTY + FOLDER "tests") diff --git a/tests/fuzz/clsag.cpp b/tests/fuzz/clsag.cpp new file mode 100644 index 000000000..825b4c243 --- /dev/null +++ b/tests/fuzz/clsag.cpp @@ -0,0 +1,52 @@ +// Copyright (c) 2017-2026, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "serialization/binary_utils.h" +#include "fuzzer.h" +#include "clsag_init.h" + +#include + +using namespace rct; + +BEGIN_INIT_SIMPLE_FUZZER() + clsag_init(); +END_INIT_SIMPLE_FUZZER() + +BEGIN_SIMPLE_FUZZER() + if (len > 4096) + return 0; + + // fuzz deserialization + clsag sig; + const std::string blob(reinterpret_cast(buf), len); + if (!serialization::parse_binary(blob, sig)) + return 0; + + verRctCLSAGSimple(message, sig, pubs, Cout); +END_SIMPLE_FUZZER() diff --git a/tests/fuzz/clsag_cout.cpp b/tests/fuzz/clsag_cout.cpp new file mode 100644 index 000000000..a5014566d --- /dev/null +++ b/tests/fuzz/clsag_cout.cpp @@ -0,0 +1,50 @@ +// Copyright (c) 2017-2026, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "fuzzer.h" +#include "clsag_init.h" + +#include + +using namespace rct; + +static_assert(sizeof(key) == 32, "rct::key must be 32 bytes"); + +BEGIN_INIT_SIMPLE_FUZZER() + clsag_init(); +END_INIT_SIMPLE_FUZZER() + +BEGIN_SIMPLE_FUZZER() + if (len < sizeof(key)) + return 0; + + // fuzz Cout + key cout = Cout; + std::memcpy(&cout, buf, sizeof(key)); + verRctCLSAGSimple(message, clsag_s, pubs, cout); +END_SIMPLE_FUZZER() diff --git a/tests/fuzz/clsag_init.h b/tests/fuzz/clsag_init.h new file mode 100644 index 000000000..ab4fd6347 --- /dev/null +++ b/tests/fuzz/clsag_init.h @@ -0,0 +1,81 @@ +// Copyright (c) 2017-2026, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cryptonote_basic/cryptonote_basic.h" +#include "misc_log_ex.h" +#include "ringct/rctSigs.h" + +using namespace crypto; +using namespace rct; + +static key message; +static ctkeyV pubs; +static key Cout; +static clsag clsag_s; + +inline static void clsag_init() { + message = identity(); + + const size_t N = 11; + const size_t idx = 5; + + pubs.clear(); + pubs.reserve(N); + + for (size_t i = 0; i < N; ++i) + { + key sk; + ctkey tmp; + + skpkGen(sk, tmp.dest); + skpkGen(sk, tmp.mask); + + pubs.push_back(tmp); + } + + // Set P[idx] + key p; + skpkGen(p, pubs[idx].dest); + + // Set C[idx] + key t = skGen(); + key u = skGen(); + addKeys2(pubs[idx].mask,t,u,H); + + // Set commitment offset + key t2 = skGen(); + addKeys2(Cout,t2,u,H); + + // Prepare generation inputs + ctkey insk; + insk.dest = p; + insk.mask = t; + + clsag_s = proveRctCLSAGSimple(message, pubs, insk, t2, Cout, idx, hw::get_device("default")); + CHECK_AND_ASSERT_THROW_MES(verRctCLSAGSimple(message, clsag_s, pubs, Cout), "Generated CLSAG does not verify"); +} diff --git a/tests/fuzz/clsag_message.cpp b/tests/fuzz/clsag_message.cpp new file mode 100644 index 000000000..044140e20 --- /dev/null +++ b/tests/fuzz/clsag_message.cpp @@ -0,0 +1,51 @@ +// Copyright (c) 2017-2026, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "fuzzer.h" +#include "clsag_init.h" + +#include + +using namespace crypto; +using namespace rct; + +static_assert(sizeof(key) == 32, "rct::key must be 32 bytes"); + +BEGIN_INIT_SIMPLE_FUZZER() + clsag_init(); +END_INIT_SIMPLE_FUZZER() + +BEGIN_SIMPLE_FUZZER() + if (len < sizeof(key)) + return 0; + + // fuzz message + key fuzzed_message = message; + std::memcpy(&fuzzed_message, buf, sizeof(key)); + verRctCLSAGSimple(fuzzed_message, clsag_s, pubs, Cout); +END_SIMPLE_FUZZER() diff --git a/tests/fuzz/clsag_pubs.cpp b/tests/fuzz/clsag_pubs.cpp new file mode 100644 index 000000000..385ddc566 --- /dev/null +++ b/tests/fuzz/clsag_pubs.cpp @@ -0,0 +1,52 @@ +// Copyright (c) 2017-2026, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "fuzzer.h" +#include "clsag_init.h" + +#include + +using namespace rct; + +static_assert(sizeof(key) == 32, "rct::key must be 32 bytes"); + +BEGIN_INIT_SIMPLE_FUZZER() + clsag_init(); +END_INIT_SIMPLE_FUZZER() + +BEGIN_SIMPLE_FUZZER() + if (len < sizeof(key) + 2) + return 0; + + ctkeyV fuzzed_pubs = pubs; + const size_t index = buf[0] % fuzzed_pubs.size(); + key& pub = (buf[1] & 1) ? fuzzed_pubs[index].mask : fuzzed_pubs[index].dest; + std::memcpy(&pub, buf + 2, sizeof(key)); + + verRctCLSAGSimple(message, clsag_s, fuzzed_pubs, Cout); +END_SIMPLE_FUZZER()