Skip to content

Commit 16fbe8d

Browse files
committed
Java: add dataflow test for newly added KDF API
1 parent b4e6d30 commit 16fbe8d

File tree

4 files changed

+95
-0
lines changed

4 files changed

+95
-0
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import javax.crypto.KDF;
2+
import javax.crypto.spec.HKDFParameterSpec;
3+
4+
public class KDFDataflowTest {
5+
public static void main(String[] args) throws Exception {
6+
String userInput = args[0]; // source
7+
byte[] taintedBytes = userInput.getBytes();
8+
9+
testBuilderPattern(taintedBytes);
10+
testSeparateBuilder(taintedBytes);
11+
testKDFWithSalt(taintedBytes);
12+
testStaticParameterSpec(taintedBytes);
13+
testCleanUsage();
14+
}
15+
16+
public static void testBuilderPattern(byte[] taintedIKM) throws Exception {
17+
HKDFParameterSpec.Builder builder = HKDFParameterSpec.ofExtract();
18+
builder.addIKM(taintedIKM);
19+
HKDFParameterSpec spec = builder.thenExpand("info".getBytes(), 32);
20+
21+
KDF kdf = KDF.getInstance("HKDF-SHA256");
22+
byte[] result = kdf.deriveData(spec);
23+
sink(result); // should flag
24+
}
25+
26+
public static void testSeparateBuilder(byte[] taintedIKM) throws Exception {
27+
HKDFParameterSpec.Builder builder1 = HKDFParameterSpec.ofExtract();
28+
HKDFParameterSpec.Builder builder2 = builder1.addIKM(taintedIKM);
29+
HKDFParameterSpec spec = builder2.thenExpand("info".getBytes(), 32);
30+
31+
KDF kdf = KDF.getInstance("HKDF-SHA256");
32+
byte[] result = kdf.deriveData(spec);
33+
sink(result); // should flag
34+
}
35+
36+
public static void sink(Object o) {}
37+
38+
public static void testKDFWithSalt(byte[] taintedIKM) throws Exception {
39+
HKDFParameterSpec.Builder builder = HKDFParameterSpec.ofExtract();
40+
builder.addIKM(taintedIKM);
41+
builder.addSalt("sensitive-salt".getBytes());
42+
HKDFParameterSpec spec = builder.thenExpand("info".getBytes(), 32);
43+
44+
KDF kdf = KDF.getInstance("HKDF-SHA256");
45+
byte[] result = kdf.deriveData(spec);
46+
sink(result); // should flag
47+
}
48+
49+
public static void testStaticParameterSpec(byte[] taintedIKM) throws Exception {
50+
javax.crypto.spec.SecretKeySpec secretKey = new javax.crypto.spec.SecretKeySpec(taintedIKM, "AES");
51+
HKDFParameterSpec spec = HKDFParameterSpec.expandOnly(
52+
secretKey, "info".getBytes(), 32);
53+
54+
KDF kdf = KDF.getInstance("HKDF-SHA256");
55+
byte[] result = kdf.deriveData(spec);
56+
sink(result); // should flag
57+
}
58+
59+
public static void testCleanUsage() throws Exception {
60+
byte[] cleanKeyMaterial = "static-key-material".getBytes();
61+
62+
HKDFParameterSpec.Builder builder = HKDFParameterSpec.ofExtract();
63+
builder.addIKM(cleanKeyMaterial); // clean input
64+
HKDFParameterSpec spec = builder.thenExpand("info".getBytes(), 32);
65+
66+
KDF kdf = KDF.getInstance("HKDF-SHA256");
67+
byte[] cleanResult = kdf.deriveData(spec);
68+
sink(cleanResult); // should NOT flag - no taint source
69+
}
70+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
//semmle-extractor-options: --javac-args --enable-preview --release 25

java/ql/test/library-tests/dataflow/kdf/test.expected

Whitespace-only changes.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import java
2+
import semmle.code.java.dataflow.TaintTracking
3+
4+
module Config implements DataFlow::ConfigSig {
5+
predicate isSource(DataFlow::Node n) {
6+
exists(ArrayAccess aa |
7+
aa.getArray().(VarAccess).getVariable().hasName("args") and
8+
n.asExpr() = aa
9+
)
10+
}
11+
12+
predicate isSink(DataFlow::Node n) {
13+
exists(MethodCall ma |
14+
ma.getMethod().hasName("sink") and
15+
n.asExpr() = ma.getAnArgument()
16+
)
17+
}
18+
}
19+
20+
module Flow = TaintTracking::Global<Config>;
21+
22+
from DataFlow::Node src, DataFlow::Node sink
23+
where Flow::flow(src, sink)
24+
select src, sink

0 commit comments

Comments
 (0)