diff --git a/sdk/fuzz.sh b/sdk/fuzz.sh
new file mode 100755
index 00000000..88a803ae
--- /dev/null
+++ b/sdk/fuzz.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+set -e
+
+tests=("fuzzNanoTDF", "fuzzTDF", "fuzzZipRead")
+base_seed_dir="src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/"
+
+for test in "${tests[@]}"; do
+ seed_dir="${base_seed_dir}${test}"
+ echo "Running $test fuzzing with seeds from $seed_dir"
+ mvn verify -P fuzz -Djazzer.testDir=$seed_dir
+done
diff --git a/sdk/pom.xml b/sdk/pom.xml
index 678c78b0..6685f513 100644
--- a/sdk/pom.xml
+++ b/sdk/pom.xml
@@ -9,6 +9,10 @@
0.7.5
jar
+
+ 0.22.1
+ https://github.com/CodeIntelligenceTesting/jazzer/releases/download/v${jazzer.version}
+
@@ -121,6 +125,18 @@
4.13.2
test
+
+ com.code-intelligence
+ jazzer-api
+ ${jazzer.version}
+ test
+
+
+ com.code-intelligence
+ jazzer-junit
+ ${jazzer.version}
+ test
+
org.apache.commons
commons-compress
@@ -307,4 +323,110 @@
-
\ No newline at end of file
+
+
+
+ fuzz
+
+ false
+
+
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+ 3.1.0
+
+
+ download-and-unpack-jazzer
+ process-test-classes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ run
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ 3.4.0
+
+
+ copy-dependencies
+ process-test-classes
+
+ copy-dependencies
+
+
+ ${project.build.directory}/dependency-jars
+ test
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+ 3.1.0
+
+
+ run-jazzer-fuzzing
+ verify
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ run
+
+
+
+
+
+
+
+
+
diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/Fuzzing.java b/sdk/src/test/java/io/opentdf/platform/sdk/Fuzzing.java
new file mode 100644
index 00000000..776a107e
--- /dev/null
+++ b/sdk/src/test/java/io/opentdf/platform/sdk/Fuzzing.java
@@ -0,0 +1,69 @@
+package io.opentdf.platform.sdk;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.security.NoSuchAlgorithmException;
+import java.text.ParseException;
+
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import com.code_intelligence.jazzer.junit.FuzzTest;
+import com.google.gson.JsonParseException;
+import com.nimbusds.jose.JOSEException;
+
+import io.opentdf.platform.sdk.TDF.FailedToCreateGMAC;
+import io.opentdf.platform.sdk.TDF.Reader;
+
+public class Fuzzing {
+ private static final String testDuration = "600s";
+ private static final OutputStream ignoreOutputStream = new OutputStream() {
+ @Override
+ public void write(int b) {
+ // ignored
+ }
+
+ @Override
+ public void write(byte b[], int off, int len) {
+ // ignored
+ }
+ };
+
+ @FuzzTest(maxDuration=testDuration)
+ public void fuzzNanoTDF(FuzzedDataProvider data) throws IOException {
+ byte[] fuzzBytes = data.consumeRemainingAsBytes();
+ NanoTDF nanoTDF = new NanoTDF();
+ nanoTDF.readNanoTDF(ByteBuffer.wrap(fuzzBytes), ignoreOutputStream, NanoTDFTest.kas);
+ }
+
+ @FuzzTest(maxDuration=testDuration)
+ public void fuzzTDF(FuzzedDataProvider data) throws FailedToCreateGMAC, NoSuchAlgorithmException, IOException, JOSEException, ParseException, DecoderException {
+ byte[] fuzzBytes = data.consumeRemainingAsBytes();
+ byte[] key = new byte[32]; // use consistent zero key for performance and so fuzz can relate to seed
+ var assertionVerificationKeys = new Config.AssertionVerificationKeys();
+ assertionVerificationKeys.defaultKey = new AssertionConfig.AssertionKey(AssertionConfig.AssertionKeyAlg.HS256, key);
+ Config.TDFReaderConfig readerConfig = Config.newTDFReaderConfig(
+ Config.withAssertionVerificationKeys(assertionVerificationKeys));
+ TDF tdf = new TDF();
+
+ try {
+ Reader reader = tdf.loadTDF(new SeekableInMemoryByteChannel(fuzzBytes), TDFTest.kas, readerConfig);
+
+ reader.readPayload(ignoreOutputStream);
+ } catch (SDKException | InvalidZipException | JsonParseException | IOException | IllegalArgumentException e) {
+ // expected failure cases
+ }
+ }
+
+ @FuzzTest(maxDuration=testDuration)
+ public void fuzzZipRead(FuzzedDataProvider data) {
+ byte[] fuzzBytes = data.consumeRemainingAsBytes();
+ try {
+ ZipReaderTest.testReadingZipChannel(new SeekableInMemoryByteChannel(fuzzBytes), false);
+ } catch (InvalidZipException | IllegalArgumentException | JsonParseException | IOException e) {
+ // cases which are expected with invalid fuzzed inputs
+ }
+ }
+}
diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/NanoTDFTest.java b/sdk/src/test/java/io/opentdf/platform/sdk/NanoTDFTest.java
index 87bae33b..cd4c056d 100644
--- a/sdk/src/test/java/io/opentdf/platform/sdk/NanoTDFTest.java
+++ b/sdk/src/test/java/io/opentdf/platform/sdk/NanoTDFTest.java
@@ -37,7 +37,7 @@ public class NanoTDFTest {
private static final String KID = "r1";
- private static SDK.KAS kas = new SDK.KAS() {
+ protected static SDK.KAS kas = new SDK.KAS() {
@Override
public void close() throws Exception {
}
diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/ZipReaderTest.java b/sdk/src/test/java/io/opentdf/platform/sdk/ZipReaderTest.java
index 5c47710c..29769b2b 100644
--- a/sdk/src/test/java/io/opentdf/platform/sdk/ZipReaderTest.java
+++ b/sdk/src/test/java/io/opentdf/platform/sdk/ZipReaderTest.java
@@ -12,9 +12,13 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
+import java.nio.channels.SeekableByteChannel;
import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
@@ -32,21 +36,31 @@ public class ZipReaderTest {
public void testReadingExistingZip() throws Exception {
try (RandomAccessFile raf = new RandomAccessFile("src/test/resources/sample.txt.tdf", "r")) {
var fileChannel = raf.getChannel();
- var zipReader = new ZipReader(fileChannel);
- var entries = zipReader.getEntries();
+ ZipReaderTest.testReadingZipChannel(fileChannel, true);
+ }
+ }
+
+ protected static void testReadingZipChannel(SeekableByteChannel fileChannel, boolean test) throws IOException {
+ var zipReader = new ZipReader(fileChannel);
+ var entries = zipReader.getEntries();
+ if (test) {
assertThat(entries.size()).isEqualTo(2);
- for (var entry: entries) {
- var stream = new ByteArrayOutputStream();
- if (entry.getName().endsWith(".json")) {
- entry.getData().transferTo(stream);
- var data = stream.toString(StandardCharsets.UTF_8);
- var gson = new GsonBuilder()
- .registerTypeAdapter(Manifest.class, new ManifestDeserializer())
- .create();
- var map = gson.fromJson(data, Map.class);
-
+ }
+ for (var entry: entries) {
+ var stream = new ByteArrayOutputStream();
+ if (entry.getName().endsWith(".json")) {
+ entry.getData().transferTo(stream);
+ var data = stream.toString(StandardCharsets.UTF_8);
+ var gson = new GsonBuilder()
+ .registerTypeAdapter(Manifest.class, new ManifestDeserializer())
+ .create();
+ var map = gson.fromJson(data, Map.class);
+
+ if (test) {
assertThat(map.get("encryptionInformation")).isNotNull();
}
+ } else if (!test) {
+ entry.getData().transferTo(stream); // still invoke getData logic
}
}
}
diff --git a/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzNanoTDF/sample.ntdf b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzNanoTDF/sample.ntdf
new file mode 100644
index 00000000..7dd6dcbb
Binary files /dev/null and b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzNanoTDF/sample.ntdf differ
diff --git a/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-1 b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-1
new file mode 100644
index 00000000..5e0b5c99
Binary files /dev/null and b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-1 differ
diff --git a/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-2 b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-2
new file mode 100644
index 00000000..de7914cd
Binary files /dev/null and b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-2 differ
diff --git a/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-3 b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-3
new file mode 100644
index 00000000..bfe79806
Binary files /dev/null and b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-3 differ
diff --git a/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-4 b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-4
new file mode 100644
index 00000000..da6463a9
Binary files /dev/null and b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-4 differ
diff --git a/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-NullKeyAccessObj b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-NullKeyAccessObj
new file mode 100644
index 00000000..d55d907b
Binary files /dev/null and b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-NullKeyAccessObj differ
diff --git a/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-NullSegment b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-NullSegment
new file mode 100644
index 00000000..4537beda
Binary files /dev/null and b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/crash-InvalidManifest-NullSegment differ
diff --git a/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/sample.tdf b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/sample.tdf
new file mode 100644
index 00000000..cc27081a
Binary files /dev/null and b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzTDF/sample.tdf differ
diff --git a/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzZipRead/crash-NullSignature b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzZipRead/crash-NullSignature
new file mode 100644
index 00000000..24ea0b1c
Binary files /dev/null and b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzZipRead/crash-NullSignature differ
diff --git a/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzZipRead/crash-f39ad8416aef7cf275f84683aaa0efd15f24272a b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzZipRead/crash-f39ad8416aef7cf275f84683aaa0efd15f24272a
new file mode 100644
index 00000000..2fc1da22
Binary files /dev/null and b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzZipRead/crash-f39ad8416aef7cf275f84683aaa0efd15f24272a differ
diff --git a/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzZipRead/sample.txt.tdf b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzZipRead/sample.txt.tdf
new file mode 100644
index 00000000..2bb81265
Binary files /dev/null and b/sdk/src/test/resources/io/opentdf/platform/sdk/FuzzingInputs/fuzzZipRead/sample.txt.tdf differ