Integration of pw_fuzzer using FuzzTest (#34274)

* latest trial to build pw_fuzz

* migrating FuzzPayloadDecoder FuzzTest

* fix error related to latomic

* adding template for pw_fuzz_tests

* fix for linux_sysroot issue

* adding FuzzTests

* fixing warning issue

* adding support to build pw-fuzztests with build_examples.py

* Restyled by whitespace

* Restyled by clang-format

* adding pw_fuzz_tests to default target

* fixing build_examples test golden standard

* Adding Fuzzing Targets

* Adding Documentation

* cleaning-up tests

* spelling mistakes

* integrating comments

---------

Co-authored-by: Restyled.io <commits@restyled.io>
diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt
index 1533458..4444d82 100644
--- a/.github/.wordlist.txt
+++ b/.github/.wordlist.txt
@@ -37,6 +37,7 @@
 AE
 aef
 AES
+AFL
 AIDL
 algs
 alloc
@@ -570,6 +571,7 @@
 ftd
 fullclean
 fuzzer
+fuzztest
 FW
 gbl
 gcloud
@@ -1008,6 +1010,7 @@
 optionsMask
 optionsOverride
 orgs
+OSS
 OTA
 OTADownloader
 otaDownloadPath
diff --git a/.gitmodules b/.gitmodules
index 78a6cab..40801ec 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -329,3 +329,19 @@
 	path = third_party/infineon/psoc6/psoc6_sdk/libs/lwip-network-interface-integration
 	url = https://github.com/Infineon/lwip-network-interface-integration.git
 	platforms = infineon
+[submodule "third_party/abseil-cpp/src"]
+	path = third_party/abseil-cpp/src
+	url = https://github.com/abseil/abseil-cpp.git
+	platforms = linux,darwin
+[submodule "third_party/fuzztest"]
+	path = third_party/fuzztest
+	url = https://github.com/google/fuzztest.git
+	platforms = linux,darwin
+[submodule "third_party/googletest"]
+	path = third_party/googletest
+	url = https://github.com/google/googletest
+	platforms = linux,darwin
+[submodule "third_party/re2/src"]
+	path = third_party/re2/src
+	url = https://github.com/google/re2.git
+	platforms = linux,darwin
diff --git a/BUILD.gn b/BUILD.gn
index c8e4197..4efa250 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -62,6 +62,18 @@
     }
   }
 
+  if (pw_enable_fuzz_test_targets) {
+    group("pw_fuzz_tests") {
+      deps = [
+        "${chip_root}/src/credentials/tests:fuzz-chip-cert-pw(//build/toolchain/pw_fuzzer:chip_pw_fuzztest)",
+        "${chip_root}/src/lib/core/tests:fuzz-tlv-reader-pw(//build/toolchain/pw_fuzzer:chip_pw_fuzztest)",
+        "${chip_root}/src/lib/dnssd/minimal_mdns/tests:fuzz-minmdns-packet-parsing-pw(//build/toolchain/pw_fuzzer:chip_pw_fuzztest)",
+        "${chip_root}/src/lib/format/tests:fuzz-payload-decoder-pw(//build/toolchain/pw_fuzzer:chip_pw_fuzztest)",
+        "${chip_root}/src/setup_payload/tests:fuzz-setup-payload-base38-pw(//build/toolchain/pw_fuzzer:chip_pw_fuzztest)",
+      ]
+    }
+  }
+
   # Matter's in-tree pw_python_package or pw_python_distribution targets.
   _matter_python_packages = [
     "//examples/chef",
@@ -140,6 +152,10 @@
       deps += [ "//:fuzz_tests" ]
     }
 
+    if (pw_enable_fuzz_test_targets) {
+      deps += [ "//:pw_fuzz_tests" ]
+    }
+
     if (chip_device_platform != "none") {
       deps += [ "${chip_root}/src/app/server" ]
     }
diff --git a/build/chip/fuzz_test.gni b/build/chip/fuzz_test.gni
index 784ed60..98def1d 100644
--- a/build/chip/fuzz_test.gni
+++ b/build/chip/fuzz_test.gni
@@ -14,12 +14,17 @@
 
 import("//build_overrides/build.gni")
 import("//build_overrides/chip.gni")
+import("//build_overrides/pigweed.gni")
+
 import("${build_root}/config/compiler/compiler.gni")
 import("${chip_root}/build/chip/tests.gni")
+import("${dir_pw_unit_test}/test.gni")
 
 declare_args() {
   enable_fuzz_test_targets = is_clang && chip_build_tests &&
                              (current_os == "linux" || current_os == "mac")
+
+  pw_enable_fuzz_test_targets = false
 }
 
 # Define a fuzz target for chip.
@@ -66,3 +71,57 @@
     }
   }
 }
+
+# Define a fuzz target for Matter using pw_fuzzer and Google FuzzTest Framework.
+#
+# Google FuzzTest is only supported on Linux and MacOS using Clang:
+#
+# Sample usage
+#
+# chip_pw_fuzz_target("fuzz-target-name") {
+#   test_source = [
+#      "FuzzTarget.cpp", # Fuzz target
+#   ]
+#
+#   public_deps = [
+#     "${chip_root}/src/lib/foo",         # add dependencies here
+#   ]
+# }
+#
+#
+template("chip_pw_fuzz_target") {
+  if (defined(invoker.test_source)) {
+    _test_output_dir = "${root_out_dir}/tests"
+
+    if (defined(invoker.output_dir)) {
+      _test_output_dir = invoker.output_dir
+    }
+
+    pw_test(target_name) {
+      forward_variables_from(invoker,
+                             [
+                               "deps",
+                               "public_deps",
+                               "cflags",
+                               "configs",
+                               "remove_configs",
+                             ])
+
+      # TODO: remove this after pw_fuzzer's integration with OSS-Fuzz is complete.
+      #just a test for running FuzzTest with libfuzzer-compatibility mode, since this is the mode supported by OSS-fuzz
+      # defines = [
+      # "FUZZTEST_COMPATIBILITY_MODE=libfuzzer",
+      #   "MAKE_BUILD_TYPE=RelWithDebug",
+      #  ]
+
+      sources = invoker.test_source
+      output_dir = _test_output_dir
+
+      deps = [ "$dir_pw_fuzzer:fuzztest" ]
+
+      # this is necessary so FuzzTest is compiled into an executable in third_party/pigweed/repo/pw_unit_test/test.gni
+      # otherwise it will be built successfully but with FuzzTarget.DISABLED.ninja and no executable.
+      enable_if = true
+    }
+  }
+}
diff --git a/build/toolchain/pw_fuzzer/BUILD.gn b/build/toolchain/pw_fuzzer/BUILD.gn
new file mode 100644
index 0000000..385e57c
--- /dev/null
+++ b/build/toolchain/pw_fuzzer/BUILD.gn
@@ -0,0 +1,70 @@
+# Copyright (c) 2024 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+import("//build_overrides/pigweed.gni")
+
+import("$dir_pigweed/targets/host/target_toolchains.gni")
+import("${build_root}/toolchain/gcc_toolchain.gni")
+
+# creating a secondary toolchain to be used with pw_fuzzer FuzzTests
+# This toolchain is downstreamed from pigweed's pw_target_toolchain_host.clang_fuzz
+# it allows us to specifically use googletest for fuzzing (instead of the lighter version of googletest used for unit testing)
+
+gcc_toolchain("chip_pw_fuzztest") {
+  forward_variables_from(pw_target_toolchain_host.clang_fuzz, "*", [ "name" ])
+
+  toolchain_args = {
+    # This is needed to have the defaults passed from pw_target_toolchain_host.clang_fuzz to the current scope
+    forward_variables_from(defaults, "*")
+
+    pw_unit_test_MAIN = "$dir_pw_fuzzer:fuzztest_main"
+    pw_unit_test_BACKEND = "$dir_pw_fuzzer:gtest"
+
+    # The next three lines are needed by the gcc_toolchain template
+    current_os = host_os
+    current_cpu = host_cpu
+    is_clang = true
+
+    # the upstream pigweed host_clang toolchain defines a default sysroot, which results in build errors
+    # since it does not include SSL lib and is supposed to be minimal by design.
+    # by removing this default config, we will use the system's libs. Otherwise we can define our own sysroot.
+    # discussion on: https://discord.com/channels/691686718377558037/1275092695764959232
+    remove_default_configs = [ "$dir_pw_toolchain/host_clang:linux_sysroot" ]
+
+    # when is_debug = true, we pass -O0 to cflags and ldflags, while upstream pw_fuzzer toolchain defines "optimize_speed" config that passes -O2.
+    # This condition was added to prevent mixing the flags
+    if (is_debug) {
+      remove_default_configs += [ "$dir_pw_build:optimize_speed" ]
+    }
+
+    # removing pigweed downstreamed configs related to warnings
+    # These are triggering an error related to -Wcast-qual in third_party/nlio
+    remove_default_configs += [
+      "$dir_pw_build:strict_warnings",
+      "$dir_pw_build:extra_strict_warnings",
+    ]
+
+    # the third_party abseil-cpp triggers warnings related to [-Wformat-nonliteral]
+    treat_warnings_as_errors = false
+
+    dir_pw_third_party_abseil_cpp = "//third_party/abseil-cpp/src"
+    dir_pw_third_party_fuzztest = "//third_party/fuzztest"
+    dir_pw_third_party_googletest = "//third_party/googletest"
+
+    # TODO: Seems that re2 support within FuzzTest was deprecated, keeping it defined is triggering warning
+    # Remove if re2 is indeed not needed
+    # dir_pw_third_party_re2 = "//third_party/re2/src"
+  }
+}
diff --git a/docs/guides/BUILDING.md b/docs/guides/BUILDING.md
index 7cd6602..941b532 100644
--- a/docs/guides/BUILDING.md
+++ b/docs/guides/BUILDING.md
@@ -382,6 +382,26 @@
 
 You likely want `libfuzzer` + `asan` builds instead for local testing.
 
+### `pw_fuzzer` `FuzzTests`
+
+An Alternative way for writing and running Fuzz Tests is Google's `FuzzTest`
+framework, integrated through `pw_fuzzer`. The Tests will have to be built and
+executed manually.
+
+```
+./scripts/build/build_examples.py --target linux-x64-tests-clang-pw-fuzztest build
+```
+
+NOTE: `asan` is enabled by default in FuzzTest, so please do not add it in
+build_examples.py invocation.
+
+Tests will be located in:
+`out/linux-x64-tests-clang-pw-fuzztest/chip_pw_fuzztest/tests/` where
+`chip_pw_fuzztest` is the name of the toolchain used.
+
+-   Details on How To Run Fuzz Tests in
+    [Running FuzzTests](https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/fuzz_testing.md)
+
 ## Build custom configuration
 
 The build is configured by setting build arguments. These you can set in one of
diff --git a/docs/testing/fuzz_testing.md b/docs/testing/fuzz_testing.md
new file mode 100644
index 0000000..b7faeae
--- /dev/null
+++ b/docs/testing/fuzz_testing.md
@@ -0,0 +1,157 @@
+# Fuzz testing
+
+-   Fuzz Testing involves providing random and unexpected data as input to
+    functions and methods to uncover bugs, security vulnerabilities, or to
+    determine if the software crashes.
+-   it is often continuous; the function under test is called in iteration with
+    thousands of different inputs.
+-   Fuzz testing is often done with sanitizers enabled; to catch memory errors
+    and undefined behavior.
+-   The most commonly used fuzz testing frameworks for C/C++ are LibFuzzer and
+    AFL.
+-   [Google's FuzzTest](https://github.com/google/fuzztest) is a newer framework
+    that simplifies writing fuzz tests with user-friendly APIs and offers more
+    control over input generation. It also integrates seamlessly with Google
+    Test (GTest).
+
+## `Google's FuzzTest`
+
+-   Google FuzzTest is integrated through Pigweed
+    [pw_fuzzer](https://pigweed.dev/pw_fuzzer/concepts.html).
+
+### Use cases
+
+1. Finding Undefined Behavior with Sanitizers:
+
+    - Running fuzz tests while checking if a crash or other sanitizer-detected
+      error occurs, allowing detection of subtle memory issues like buffer
+      overflows and use-after-free errors.
+
+2. Find Correctness Bugs using Assertions:
+    - For example, in Round trip Fuzzing, fuzzed input is encoded, decoded, and
+      then verified to match the original input. An example of this can be found
+      in src/setup_payload/tests/FuzzBase38PW.cpp.
+
+-   More information can be found in the
+    [FuzzTest Use Cases](https://github.com/google/fuzztest/blob/main/doc/use-cases.md)
+    documentation.
+
+### Writing FuzzTests
+
+Keywords: Property Function, Input Domain
+
+-   FuzzTests are instantiated through the macro call of `FUZZ_TEST`:
+
+```cpp
+FUZZ_TEST(TLVReader, FuzzTlvReader).WithDomains(fuzztest::Arbitrary<std::vector<std::uint8_t>>());
+```
+
+-   The Macro invocation calls the **Property Function**, which is
+    `FuzzTlvReader` above.
+
+-   The **input domains** define the range and type of inputs that the
+    **property function** will receive during fuzzing, specified using the
+    `.WithDomains()` clause.
+-   In the macro above, FuzzTest will generate a wide range of possible byte
+    vectors to thoroughly test the `FuzzTlvReader` function.
+
+#### The Property Function
+
+```cpp
+// The Property Function
+void FuzzTlvRead(const std::vector<std::uint8_t> & bytes)
+{
+    TLVReader reader;
+    reader.Init(bytes.data(), bytes.size());
+    chip::TLV::Utilities::Iterate(reader, FuzzIterator, nullptr);
+}
+```
+
+-   The Property Functions must return a `void`
+-   The function will be run with many different inputs in the same process,
+    trying to trigger a crash.
+-   It is possible to include Assertions such as during Round-Trip Fuzzing
+
+-   More Information:
+    https://github.com/google/fuzztest/blob/main/doc/fuzz-test-macro.md#the-property-function
+
+#### Input Domains
+
+-   FuzzTest Offers many Input Domains, all of which are part of the
+    `fuzztest::` namespace.
+-   All native C++ types can be used through `Arbitrary<T>()`:
+
+```cpp
+FUZZ_TEST(Base38Decoder, FuzzQRCodeSetupPayloadParser).WithDomains(Arbitrary<std::string>());
+```
+
+-   using vector domains is one of the most common. It is possible to limit the
+    size of the input vectors (or any container domain) using `.WithMaxSize()`
+    or `.WithMinSize()`, as shown below:
+
+```cpp
+FUZZ_TEST(MinimalmDNS, TxtResponderFuzz).WithDomains(Arbitrary<vector<uint8_t>>().WithMaxSize(254));
+```
+
+-   `ElementOf` is particularly useful as it allows us to define a domain by
+    explicitly enumerating the set of values in it and passing it to FuzzTest
+    invocation. Example:
+
+```cpp
+auto AnyProtocolID()
+{
+    return ElementOf({ chip::Protocols::SecureChannel::Id, chip::Protocols::InteractionModel::Id, chip::Protocols::BDX::Id,
+                       chip::Protocols::UserDirectedCommissioning::Id });
+}
+
+FUZZ_TEST(PayloadDecoder, RunDecodeFuzz).WithDomains(Arbitrary<std::vector<std::uint8_t>>(), AnyProtocolID(), Arbitrary<uint8_t>());
+```
+
+-   A detailed reference for input domains can be found here:
+    [FuzzTest Domain Reference](https://github.com/google/fuzztest/blob/main/doc/domains-reference.md#elementof-domains-element-of).
+
+### Running FuzzTests
+
+There are several ways to run the tests:
+
+1.  Unit-test mode (where the inputs are only fuzzed for a second):
+
+```bash
+./fuzz-chip-cert-pw
+```
+
+2.  Continuous fuzzing mode; we need to first list the tests, then specify the
+    FuzzTestCase to run:
+
+```bash
+$ ./fuzz-chip-cert-pw --list_fuzz_tests
+[.] Sanitizer coverage enabled. Counter map size: 11134, Cmp map size: 262144
+[*] Fuzz test: ChipCert.ChipCertFuzzer
+[*] Fuzz test: ChipCert.DecodeChipCertFuzzer
+
+$ ./fuzz-chip-cert-pw --fuzz=ChipCert.DecodeChipCertFuzzer
+```
+
+3. Running all Tests in a TestSuite for a specific time, e.g for 10 minutes
+
+```bash
+#both Fuzz Tests will be run for 10 minutes each
+./fuzz-chip-cert-pw --fuzz_for=10m
+```
+
+4. For Help
+
+```bash
+# FuzzTest related help
+./fuzz-chip-cert-pw --helpfull
+
+# gtest related help
+./fuzz-chip-cert-pw --help
+
+```
+
+#### TO ADD:
+
+-   More Information on Test Fixtures (After issues are resolved)
+-   How to add FuzzTests to the Build System
+-   More Information on OSS-FUZZ
diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py
index efb6612..378a286 100755
--- a/scripts/build/build/targets.py
+++ b/scripts/build/build/targets.py
@@ -77,6 +77,8 @@
         "-clang").ExceptIfRe('-ossfuzz')
     target.AppendModifier("ossfuzz", fuzzing_type=HostFuzzingType.OSS_FUZZ).OnlyIfRe(
         "-clang").ExceptIfRe('-libfuzzer')
+    target.AppendModifier("pw-fuzztest", fuzzing_type=HostFuzzingType.PW_FUZZTEST).OnlyIfRe(
+        "-clang").ExceptIfRe('-(libfuzzer|ossfuzz|asan)')
     target.AppendModifier('coverage', use_coverage=True).OnlyIfRe(
         '-(chip-tool|all-clusters)')
     target.AppendModifier('dmalloc', use_dmalloc=True)
@@ -178,6 +180,8 @@
         "-clang").ExceptIfRe('-ossfuzz')
     target.AppendModifier("ossfuzz", fuzzing_type=HostFuzzingType.OSS_FUZZ).OnlyIfRe(
         "-clang").ExceptIfRe('-libfuzzer')
+    target.AppendModifier("pw-fuzztest", fuzzing_type=HostFuzzingType.PW_FUZZTEST).OnlyIfRe(
+        "-clang").ExceptIfRe('-(libfuzzer|ossfuzz|asan)')
     target.AppendModifier('coverage', use_coverage=True).OnlyIfRe(
         '-(chip-tool|all-clusters|tests)')
     target.AppendModifier('dmalloc', use_dmalloc=True)
diff --git a/scripts/build/builders/host.py b/scripts/build/builders/host.py
index c51a8ee..b69421a 100644
--- a/scripts/build/builders/host.py
+++ b/scripts/build/builders/host.py
@@ -42,6 +42,7 @@
     NONE = auto()
     LIB_FUZZER = auto()
     OSS_FUZZ = auto()
+    PW_FUZZTEST = auto()
 
 
 class HostApp(Enum):
@@ -379,6 +380,8 @@
             self.extra_gn_options.append('is_libfuzzer=true')
         elif fuzzing_type == HostFuzzingType.OSS_FUZZ:
             self.extra_gn_options.append('oss_fuzz=true')
+        elif fuzzing_type == HostFuzzingType.PW_FUZZTEST:
+            self.extra_gn_options.append('pw_enable_fuzz_test_targets=true')
 
         if imgui_ui:
             self.extra_gn_options.append('chip_examples_enable_imgui_ui=true')
@@ -468,6 +471,9 @@
         if self.app == HostApp.TESTS and fuzzing_type != HostFuzzingType.NONE:
             self.build_command = 'fuzz_tests'
 
+        if self.app == HostApp.TESTS and fuzzing_type == HostFuzzingType.PW_FUZZTEST:
+            self.build_command = 'pw_fuzz_tests'
+
     def GnBuildArgs(self):
         if self.board == HostBoard.NATIVE:
             return self.extra_gn_options
diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt
index 3c5b290..07b409c 100644
--- a/scripts/build/testdata/all_targets_linux_x64.txt
+++ b/scripts/build/testdata/all_targets_linux_x64.txt
@@ -8,8 +8,8 @@
 efr32-{brd2704b,brd4316a,brd4317a,brd4318a,brd4319a,brd4186a,brd4187a,brd2601b,brd4187c,brd4186c,brd2703a,brd4338a}-{window-covering,switch,unit-test,light,lock,thermostat,pump}[-rpc][-with-ota-requestor][-icd][-low-power][-shell][-no-logging][-openthread-mtd][-heap-monitoring][-no-openthread-cli][-show-qr-code][-wifi][-rs9116][-wf200][-siwx917][-ipv4][-additional-data-advertising][-use-ot-lib][-use-ot-coap-lib][-no-version][-skip-rps-generation]
 esp32-{m5stack,c3devkit,devkitc,qemu}-{all-clusters,all-clusters-minimal,energy-management,ota-provider,ota-requestor,shell,light,lock,bridge,temperature-measurement,ota-requestor,tests}[-rpc][-ipv6only][-tracing]
 genio-lighting-app
-linux-fake-tests[-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-coverage][-dmalloc][-clang]
-linux-{x64,arm64}-{rpc-console,all-clusters,all-clusters-minimal,chip-tool,thermostat,java-matter-controller,kotlin-matter-controller,minmdns,light,light-data-model-no-unique-id,lock,shell,ota-provider,ota-requestor,simulated-app1,simulated-app2,python-bindings,tv-app,tv-casting-app,bridge,fabric-admin,fabric-bridge,tests,chip-cert,address-resolve-tool,contact-sensor,dishwasher,microwave-oven,refrigerator,rvc,air-purifier,lit-icd,air-quality-sensor,network-manager,energy-management}[-nodeps][-nlfaultinject][-platform-mdns][-minmdns-verbose][-libnl][-same-event-loop][-no-interactive][-ipv6only][-no-ble][-no-wifi][-no-thread][-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-coverage][-dmalloc][-clang][-test][-rpc][-with-ui][-evse-test-event][-enable-dnssd-tests][-disable-dnssd-tests][-chip-casting-simplified][-data-model-check][-data-model-disabled][-data-model-enabled]
+linux-fake-tests[-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-pw-fuzztest][-coverage][-dmalloc][-clang]
+linux-{x64,arm64}-{rpc-console,all-clusters,all-clusters-minimal,chip-tool,thermostat,java-matter-controller,kotlin-matter-controller,minmdns,light,light-data-model-no-unique-id,lock,shell,ota-provider,ota-requestor,simulated-app1,simulated-app2,python-bindings,tv-app,tv-casting-app,bridge,fabric-admin,fabric-bridge,tests,chip-cert,address-resolve-tool,contact-sensor,dishwasher,microwave-oven,refrigerator,rvc,air-purifier,lit-icd,air-quality-sensor,network-manager,energy-management}[-nodeps][-nlfaultinject][-platform-mdns][-minmdns-verbose][-libnl][-same-event-loop][-no-interactive][-ipv6only][-no-ble][-no-wifi][-no-thread][-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-pw-fuzztest][-coverage][-dmalloc][-clang][-test][-rpc][-with-ui][-evse-test-event][-enable-dnssd-tests][-disable-dnssd-tests][-chip-casting-simplified][-data-model-check][-data-model-disabled][-data-model-enabled]
 linux-x64-efr32-test-runner[-clang]
 imx-{chip-tool,lighting-app,thermostat,all-clusters-app,all-clusters-minimal-app,ota-provider-app}[-release]
 infineon-psoc6-{lock,light,all-clusters,all-clusters-minimal}[-ota][-updateimage][-trustm]
diff --git a/src/credentials/tests/BUILD.gn b/src/credentials/tests/BUILD.gn
index 393b246..46e1f72 100644
--- a/src/credentials/tests/BUILD.gn
+++ b/src/credentials/tests/BUILD.gn
@@ -84,3 +84,13 @@
     ]
   }
 }
+
+if (pw_enable_fuzz_test_targets) {
+  chip_pw_fuzz_target("fuzz-chip-cert-pw") {
+    test_source = [ "FuzzChipCertPW.cpp" ]
+    public_deps = [
+      "${chip_root}/src/credentials",
+      "${chip_root}/src/platform/logging:default",
+    ]
+  }
+}
diff --git a/src/credentials/tests/FuzzChipCertPW.cpp b/src/credentials/tests/FuzzChipCertPW.cpp
new file mode 100644
index 0000000..bb929b3
--- /dev/null
+++ b/src/credentials/tests/FuzzChipCertPW.cpp
@@ -0,0 +1,95 @@
+#include <cstddef>
+#include <cstdint>
+
+#include <pw_fuzzer/fuzztest.h>
+#include <pw_unit_test/framework.h>
+
+#include "credentials/CHIPCert.h"
+
+namespace {
+
+using namespace chip;
+using namespace chip::Credentials;
+
+using namespace fuzztest;
+
+void ChipCertFuzzer(const std::vector<std::uint8_t> & bytes)
+{
+    ByteSpan span(bytes.data(), bytes.size());
+
+    {
+        NodeId nodeId;
+        FabricId fabricId;
+        (void) ExtractFabricIdFromCert(span, &fabricId);
+        (void) ExtractNodeIdFabricIdFromOpCert(span, &nodeId, &fabricId);
+    }
+
+    {
+        CATValues cats;
+        (void) ExtractCATsFromOpCert(span, cats);
+    }
+
+    {
+        Credentials::P256PublicKeySpan key;
+        (void) ExtractPublicKeyFromChipCert(span, key);
+    }
+
+    {
+        chip::System::Clock::Seconds32 rcacNotBefore;
+        (void) ExtractNotBeforeFromChipCert(span, rcacNotBefore);
+    }
+
+    {
+        Credentials::CertificateKeyId skid;
+        (void) ExtractSKIDFromChipCert(span, skid);
+    }
+
+    {
+        ChipDN subjectDN;
+        (void) ExtractSubjectDNFromChipCert(span, subjectDN);
+    }
+
+    {
+        uint8_t outCertBuf[kMaxDERCertLength];
+        MutableByteSpan outCert(outCertBuf);
+        (void) ConvertChipCertToX509Cert(span, outCert);
+    }
+
+    {
+        // TODO: #35369 Move this to a Fixture once Errors related to FuzzTest Fixtures are resolved
+        ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
+        ValidateChipRCAC(span);
+        chip::Platform::MemoryShutdown();
+    }
+}
+
+FUZZ_TEST(FuzzChipCert, ChipCertFuzzer).WithDomains(Arbitrary<std::vector<std::uint8_t>>());
+
+// The Property function for DecodeChipCertFuzzer, The FUZZ_TEST Macro will call this function.
+void DecodeChipCertFuzzer(const std::vector<std::uint8_t> & bytes, BitFlags<CertDecodeFlags> aDecodeFlag)
+{
+    ByteSpan span(bytes.data(), bytes.size());
+
+    // TODO: #34352 To Move this to a Fixture once Errors related to FuzzTest Fixtures are resolved
+    ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
+
+    ChipCertificateData certData;
+    (void) DecodeChipCert(span, certData, aDecodeFlag);
+
+    chip::Platform::MemoryShutdown();
+}
+
+// This function allows us to fuzz using one of three CertDecodeFlags flags; by using FuzzTests's `ElementOf` API, we define an
+// input domain by explicitly enumerating the set of values in it More Info:
+// https://github.com/google/fuzztest/blob/main/doc/domains-reference.md#elementof-domains-element-of
+auto AnyCertDecodeFlag()
+{
+    constexpr BitFlags<CertDecodeFlags> NullDecodeFlag;
+    constexpr BitFlags<CertDecodeFlags> GenTBSHashFlag(CertDecodeFlags::kGenerateTBSHash);
+    constexpr BitFlags<CertDecodeFlags> TrustAnchorFlag(CertDecodeFlags::kIsTrustAnchor);
+
+    return ElementOf<CertDecodeFlags>({ NullDecodeFlag, GenTBSHashFlag, TrustAnchorFlag });
+}
+
+FUZZ_TEST(FuzzChipCert, DecodeChipCertFuzzer).WithDomains(Arbitrary<std::vector<std::uint8_t>>(), AnyCertDecodeFlag());
+} // namespace
diff --git a/src/lib/core/tests/BUILD.gn b/src/lib/core/tests/BUILD.gn
index eb17707..264de2c 100644
--- a/src/lib/core/tests/BUILD.gn
+++ b/src/lib/core/tests/BUILD.gn
@@ -59,3 +59,13 @@
     ]
   }
 }
+
+if (pw_enable_fuzz_test_targets) {
+  chip_pw_fuzz_target("fuzz-tlv-reader-pw") {
+    test_source = [ "FuzzTlvReaderPW.cpp" ]
+    public_deps = [
+      "${chip_root}/src/lib/core",
+      "${chip_root}/src/platform/logging:default",
+    ]
+  }
+}
diff --git a/src/lib/core/tests/FuzzTlvReaderPW.cpp b/src/lib/core/tests/FuzzTlvReaderPW.cpp
new file mode 100644
index 0000000..4296cac
--- /dev/null
+++ b/src/lib/core/tests/FuzzTlvReaderPW.cpp
@@ -0,0 +1,35 @@
+
+#include <cstddef>
+#include <cstdint>
+
+#include <pw_fuzzer/fuzztest.h>
+#include <pw_unit_test/framework.h>
+
+#include "lib/core/TLV.h"
+#include "lib/core/TLVUtilities.h"
+
+namespace {
+
+using chip::TLV::TLVReader;
+
+using namespace fuzztest;
+
+static CHIP_ERROR FuzzIterator(const TLVReader & aReader, size_t aDepth, void * aContext)
+{
+    aReader.GetLength();
+    aReader.GetTag();
+    aReader.GetType();
+    return CHIP_NO_ERROR;
+}
+
+// The Property Function
+void FuzzTlvReader(const std::vector<std::uint8_t> & bytes)
+{
+    TLVReader reader;
+    reader.Init(bytes.data(), bytes.size());
+    chip::TLV::Utilities::Iterate(reader, FuzzIterator, nullptr);
+}
+// Fuzz tests are instantiated with the FUZZ_TEST macro
+FUZZ_TEST(TLVReader, FuzzTlvReader).WithDomains(Arbitrary<std::vector<std::uint8_t>>());
+
+} // namespace
diff --git a/src/lib/dnssd/minimal_mdns/tests/BUILD.gn b/src/lib/dnssd/minimal_mdns/tests/BUILD.gn
index 47e8365..457c11e 100644
--- a/src/lib/dnssd/minimal_mdns/tests/BUILD.gn
+++ b/src/lib/dnssd/minimal_mdns/tests/BUILD.gn
@@ -53,3 +53,13 @@
     ]
   }
 }
+
+if (pw_enable_fuzz_test_targets) {
+  chip_pw_fuzz_target("fuzz-minmdns-packet-parsing-pw") {
+    test_source = [ "FuzzPacketParsingPW.cpp" ]
+    public_deps = [
+      "${chip_root}/src/lib/dnssd/minimal_mdns",
+      "${chip_root}/src/platform/logging:default",
+    ]
+  }
+}
diff --git a/src/lib/dnssd/minimal_mdns/tests/FuzzPacketParsingPW.cpp b/src/lib/dnssd/minimal_mdns/tests/FuzzPacketParsingPW.cpp
new file mode 100644
index 0000000..aec550b
--- /dev/null
+++ b/src/lib/dnssd/minimal_mdns/tests/FuzzPacketParsingPW.cpp
@@ -0,0 +1,132 @@
+#include <cstddef>
+#include <cstdint>
+
+#include <pw_fuzzer/fuzztest.h>
+#include <pw_unit_test/framework.h>
+
+#include <lib/dnssd/minimal_mdns/Parser.h>
+#include <lib/dnssd/minimal_mdns/RecordData.h>
+
+namespace {
+
+using namespace fuzztest;
+using namespace std;
+
+using namespace chip;
+using namespace mdns::Minimal;
+
+class FuzzDelegate : public ParserDelegate
+{
+public:
+    FuzzDelegate(const mdns::Minimal::BytesRange & packet) : mPacketRange(packet) {}
+    virtual ~FuzzDelegate() {}
+
+    void OnHeader(ConstHeaderRef & header) override {}
+    void OnQuery(const QueryData & data) override {}
+    void OnResource(ResourceType type, const ResourceData & data) override
+    {
+        switch (data.GetType())
+        {
+        case QType::SRV: {
+            mdns::Minimal::SrvRecord srv;
+            (void) srv.Parse(data.GetData(), mPacketRange);
+            break;
+        }
+        case QType::A: {
+            chip::Inet::IPAddress addr;
+            (void) mdns::Minimal::ParseARecord(data.GetData(), &addr);
+            break;
+        }
+        case QType::AAAA: {
+            chip::Inet::IPAddress addr;
+            (void) mdns::Minimal::ParseAAAARecord(data.GetData(), &addr);
+            break;
+        }
+        case QType::PTR: {
+            mdns::Minimal::SerializedQNameIterator name;
+            (void) mdns::Minimal::ParsePtrRecord(data.GetData(), mPacketRange, &name);
+            break;
+        }
+        default:
+            // nothing to do
+            break;
+        }
+    }
+
+private:
+    mdns::Minimal::BytesRange mPacketRange;
+};
+
+void PacketParserFuzz(const std::vector<std::uint8_t> & bytes)
+{
+    BytesRange packet(bytes.data(), bytes.data() + bytes.size());
+    FuzzDelegate delegate(packet);
+
+    mdns::Minimal::ParsePacket(packet, &delegate);
+}
+
+FUZZ_TEST(MinimalmDNS, PacketParserFuzz).WithDomains(Arbitrary<vector<uint8_t>>());
+
+class TxtRecordAccumulator : public TxtRecordDelegate
+{
+public:
+    using DataType = vector<pair<string, string>>;
+
+    void OnRecord(const BytesRange & name, const BytesRange & value) override
+    {
+        mData.push_back(make_pair(AsString(name), AsString(value)));
+    }
+
+    DataType & Data() { return mData; }
+    const DataType & Data() const { return mData; }
+
+private:
+    DataType mData;
+
+    static string AsString(const BytesRange & range)
+    {
+        return string(reinterpret_cast<const char *>(range.Start()), reinterpret_cast<const char *>(range.End()));
+    }
+};
+
+// The Property Function
+void TxtResponderFuzz(const std::vector<std::uint8_t> & aRecord)
+{
+
+    bool equal_sign_present = false;
+    auto equal_sign_pos     = aRecord.end();
+
+    // This test is only giving a set of values, it can be gives more
+    vector<uint8_t> prefixedRecord{ static_cast<uint8_t>(aRecord.size()) };
+
+    prefixedRecord.insert(prefixedRecord.end(), aRecord.begin(), aRecord.end());
+
+    TxtRecordAccumulator accumulator;
+
+    // The Function under Test, Check that the function does not Crash
+    ParseTxtRecord(BytesRange(prefixedRecord.data(), (&prefixedRecord.back() + 1)), &accumulator);
+
+    for (auto it = aRecord.begin(); it != aRecord.end(); it++)
+    {
+        // if this is first `=` found in the fuzzed record
+        if ('=' == static_cast<char>(*it) && false == equal_sign_present)
+        {
+            equal_sign_present = true;
+            equal_sign_pos     = it;
+        }
+    }
+
+    // The Fuzzed Input (record) needs to have at least two characters in order for ParseTxtRecord to do something
+    if (aRecord.size() > 1)
+    {
+        if (true == equal_sign_present)
+        {
+            std::string input_record_value(equal_sign_pos + 1, aRecord.end());
+            EXPECT_EQ(accumulator.Data().at(0).second, input_record_value);
+        }
+    }
+}
+
+FUZZ_TEST(MinimalmDNS, TxtResponderFuzz).WithDomains(Arbitrary<vector<uint8_t>>().WithMaxSize(254));
+
+} // namespace
diff --git a/src/lib/format/tests/BUILD.gn b/src/lib/format/tests/BUILD.gn
index 840a2ee..1ce417e 100644
--- a/src/lib/format/tests/BUILD.gn
+++ b/src/lib/format/tests/BUILD.gn
@@ -57,3 +57,18 @@
     ]
   }
 }
+
+if (pw_enable_fuzz_test_targets) {
+  chip_pw_fuzz_target("fuzz-payload-decoder-pw") {
+    test_source = [ "FuzzPayloadDecoderPW.cpp" ]
+    public_deps = [
+      "${chip_root}/src/controller/data_model:cluster-tlv-metadata",
+      "${chip_root}/src/lib/core",
+      "${chip_root}/src/lib/format:flat-tree",
+      "${chip_root}/src/lib/format:protocol-decoder",
+      "${chip_root}/src/lib/format:protocol-tlv-metadata",
+      "${chip_root}/src/lib/support",
+      "${chip_root}/src/platform/logging:stdio",
+    ]
+  }
+}
diff --git a/src/lib/format/tests/FuzzPayloadDecoderPW.cpp b/src/lib/format/tests/FuzzPayloadDecoderPW.cpp
new file mode 100644
index 0000000..52b51b3
--- /dev/null
+++ b/src/lib/format/tests/FuzzPayloadDecoderPW.cpp
@@ -0,0 +1,73 @@
+/*
+ *
+ *    Copyright (c) 2020-2021 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+#include <cstddef>
+#include <cstdint>
+#include <lib/format/protocol_decoder.h>
+#include <lib/support/StringBuilder.h>
+
+#include <tlv/meta/clusters_meta.h>
+#include <tlv/meta/protocols_meta.h>
+
+#include <pw_fuzzer/fuzztest.h>
+#include <pw_unit_test/framework.h>
+
+namespace {
+
+using namespace chip::Decoders;
+using namespace chip::FlatTree;
+using namespace chip::TLV;
+using namespace chip::TLVMeta;
+using namespace fuzztest;
+
+// The Property Function; The FUZZ_TEST macro will call this function, with the fuzzed input domains
+void RunDecodeFuzz(const std::vector<std::uint8_t> & bytes, chip::Protocols::Id mProtocol, uint8_t mMessageType)
+{
+
+    PayloadDecoderInitParams params;
+    params.SetProtocolDecodeTree(chip::TLVMeta::protocols_meta).SetClusterDecodeTree(chip::TLVMeta::clusters_meta);
+
+    // Fuzzing with different Protocols
+    params.SetProtocol(mProtocol);
+
+    // Fuzzing with different MessageTypes
+    params.SetMessageType(mMessageType);
+    chip::Decoders::PayloadDecoder<64, 128> decoder(params);
+
+    chip::ByteSpan payload(bytes.data(), bytes.size());
+
+    decoder.StartDecoding(payload);
+
+    PayloadEntry entry;
+    while (decoder.Next(entry))
+    {
+        // Nothing to do ...
+    }
+}
+
+// This function allows us to fuzz using one of four protocols; by using FuzzTests's `ElementOf` API, we define an
+// input domain by explicitly enumerating the set of values in it More Info:
+// https://github.com/google/fuzztest/blob/main/doc/domains-reference.md#elementof-domains-element-of
+auto AnyProtocolID()
+{
+    return ElementOf({ chip::Protocols::SecureChannel::Id, chip::Protocols::InteractionModel::Id, chip::Protocols::BDX::Id,
+                       chip::Protocols::UserDirectedCommissioning::Id });
+}
+
+FUZZ_TEST(PayloadDecoder, RunDecodeFuzz).WithDomains(Arbitrary<std::vector<std::uint8_t>>(), AnyProtocolID(), Arbitrary<uint8_t>());
+
+} // namespace
diff --git a/src/setup_payload/tests/BUILD.gn b/src/setup_payload/tests/BUILD.gn
index 75cdb8a..fc7bd6f 100644
--- a/src/setup_payload/tests/BUILD.gn
+++ b/src/setup_payload/tests/BUILD.gn
@@ -56,3 +56,13 @@
     ]
   }
 }
+
+if (pw_enable_fuzz_test_targets) {
+  chip_pw_fuzz_target("fuzz-setup-payload-base38-pw") {
+    test_source = [ "FuzzBase38PW.cpp" ]
+    public_deps = [
+      "${chip_root}/src/platform/logging:stdio",
+      "${chip_root}/src/setup_payload",
+    ]
+  }
+}
diff --git a/src/setup_payload/tests/FuzzBase38PW.cpp b/src/setup_payload/tests/FuzzBase38PW.cpp
new file mode 100644
index 0000000..b39db09
--- /dev/null
+++ b/src/setup_payload/tests/FuzzBase38PW.cpp
@@ -0,0 +1,77 @@
+#include <cstddef>
+#include <cstdint>
+#include <iostream>
+
+#include <pw_fuzzer/fuzztest.h>
+#include <pw_unit_test/framework.h>
+
+#include "setup_payload/QRCodeSetupPayloadParser.h"
+#include <setup_payload/Base38Decode.h>
+#include <setup_payload/Base38Encode.h>
+
+namespace {
+
+using namespace fuzztest;
+using namespace chip;
+
+// The property Function
+void Base38DecodeFuzz(const std::vector<uint8_t> & bytes)
+{
+    std::string base38EncodedString(reinterpret_cast<const char *>(bytes.data()), bytes.size());
+    std::vector<uint8_t> decodedData;
+
+    // Ignoring return value, because in general the data is garbage and won't decode properly.
+    // We're just testing that the decoder does not crash on the fuzzer-generated inputs.
+    chip::base38Decode(base38EncodedString, decodedData);
+}
+
+// The invocation of the FuzzTest
+FUZZ_TEST(Base38Decoder, Base38DecodeFuzz).WithDomains(Arbitrary<std::vector<uint8_t>>());
+
+/* The property function for a base38 roundtrip Fuzzer.
+ * It starts by encoding the fuzzing value passed
+ * into Base38. The encoded value will then be decoded.
+ *
+ * The fuzzer verifies that the decoded value is the same
+ * as the one in input.*/
+void Base38RoundTripFuzz(const std::vector<uint8_t> & bytes)
+{
+
+    size_t outputSizeNeeded     = base38EncodedLength(bytes.size());
+    const size_t kMaxOutputSize = 512;
+
+    ASSERT_LT(outputSizeNeeded, kMaxOutputSize);
+
+    ByteSpan span(bytes.data(), bytes.size());
+
+    char encodedBuf[kMaxOutputSize];
+    MutableCharSpan encodedSpan(encodedBuf);
+    CHIP_ERROR encodingError = base38Encode(span, encodedSpan);
+    ASSERT_EQ(encodingError, CHIP_NO_ERROR);
+
+    std::string base38EncodedString(encodedSpan.data(), encodedSpan.size());
+
+    std::vector<uint8_t> decodedData;
+    CHIP_ERROR decodingError = base38Decode(base38EncodedString, decodedData);
+
+    ASSERT_EQ(decodingError, CHIP_NO_ERROR);
+
+    // Make sure that decoded data is equal to the original fuzzed input; the bytes vector
+    ASSERT_EQ(decodedData, bytes);
+}
+
+// Max size of the vector is defined as 306 since that will give an outputSizeNeeded of 511 which is less than the required
+// kMaxOutputSize
+FUZZ_TEST(Base38Decoder, Base38RoundTripFuzz).WithDomains(Arbitrary<std::vector<uint8_t>>().WithMaxSize(306));
+
+void FuzzQRCodeSetupPayloadParser(const std::string & s)
+{
+    chip::Platform::MemoryInit();
+
+    SetupPayload payload;
+    QRCodeSetupPayloadParser(s).populatePayload(payload);
+}
+
+FUZZ_TEST(Base38Decoder, FuzzQRCodeSetupPayloadParser).WithDomains(Arbitrary<std::string>());
+
+} // namespace
diff --git a/third_party/abseil-cpp/src b/third_party/abseil-cpp/src
new file mode 160000
index 0000000..3ab97e7
--- /dev/null
+++ b/third_party/abseil-cpp/src
@@ -0,0 +1 @@
+Subproject commit 3ab97e7212bff931a201c794fa1331960158bbfa
diff --git a/third_party/fuzztest b/third_party/fuzztest
new file mode 160000
index 0000000..6eb010c
--- /dev/null
+++ b/third_party/fuzztest
@@ -0,0 +1 @@
+Subproject commit 6eb010c7223a6aa609b94d49bfc06ac88f922961
diff --git a/third_party/googletest b/third_party/googletest
new file mode 160000
index 0000000..1d17ea1
--- /dev/null
+++ b/third_party/googletest
@@ -0,0 +1 @@
+Subproject commit 1d17ea141d2c11b8917d2c7d029f1c4e2b9769b2
diff --git a/third_party/re2/src b/third_party/re2/src
new file mode 160000
index 0000000..85dd7ad
--- /dev/null
+++ b/third_party/re2/src
@@ -0,0 +1 @@
+Subproject commit 85dd7ad833a73095ecf3e3baea608ba051bbe2c7