Skip to content

Commit 166c77d

Browse files
authored
Merge pull request #20345 from github/idrissrio/java-kdf
Java: Add MaDs for `java.crypto.KDF`
2 parents 09edc29 + 728a4af commit 166c77d

File tree

7 files changed

+230
-0
lines changed

7 files changed

+230
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Added taint flow model for `java.crypto.KDF`.

java/ql/lib/ext/javax.crypto.model.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,21 @@ extensions:
77
- ["javax.crypto", "Cipher", True, "init", "(int,Key,AlgorithmParameterSpec,SecureRandom)", "", "Argument[2]", "encryption-iv", "manual"]
88
- ["javax.crypto", "Cipher", False, "unwrap", "(byte[],String,int)", "", "Argument[0]", "credentials-key", "hq-generated"]
99
- ["javax.crypto", "CipherSpi", True, "engineUnwrap", "(byte[],String,int)", "", "Argument[0]", "credentials-key", "hq-generated"]
10+
- addsTo:
11+
pack: codeql/java-all
12+
extensible: summaryModel
13+
data:
14+
- ["javax.crypto", "KDF", False, "getInstance", "(String)", "", "Argument[0]", "ReturnValue.SyntheticField[javax.crypto.KDF.algorithm]", "value", "manual"]
15+
- ["javax.crypto", "KDF", False, "getInstance", "(String,Provider)", "", "Argument[0]", "ReturnValue.SyntheticField[javax.crypto.KDF.algorithm]", "value", "manual"]
16+
- ["javax.crypto", "KDF", False, "getInstance", "(String,String)", "", "Argument[0]", "ReturnValue.SyntheticField[javax.crypto.KDF.algorithm]", "value", "manual"]
17+
- ["javax.crypto", "KDF", False, "getInstance", "(String,KDFParameters)", "", "Argument[0]", "ReturnValue.SyntheticField[javax.crypto.KDF.algorithm]", "value", "manual"]
18+
- ["javax.crypto", "KDF", False, "getInstance", "(String,KDFParameters,Provider)", "", "Argument[0]", "ReturnValue.SyntheticField[javax.crypto.KDF.algorithm]", "value", "manual"]
19+
- ["javax.crypto", "KDF", False, "getInstance", "(String,KDFParameters,String)", "", "Argument[0]", "ReturnValue.SyntheticField[javax.crypto.KDF.algorithm]", "value", "manual"]
20+
- ["javax.crypto", "KDF", True, "getAlgorithm", "()", "", "Argument[this].SyntheticField[javax.crypto.KDF.algorithm]", "ReturnValue", "value", "manual"]
21+
- ["javax.crypto", "KDF", True, "getProvider", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
22+
- ["javax.crypto", "KDF", True, "deriveKey", "(String,AlgorithmParameterSpec)", "", "Argument[1]", "ReturnValue", "taint", "manual"]
23+
- ["javax.crypto", "KDF", True, "deriveData", "(AlgorithmParameterSpec)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
24+
- ["javax.crypto", "SecretKey", True, "getEncoded", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
1025
- addsTo:
1126
pack: codeql/java-all
1227
extensible: neutralModel

java/ql/lib/ext/javax.crypto.spec.model.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,21 @@ extensions:
77
- ["javax.crypto.spec", "GCMParameterSpec", True, "GCMParameterSpec", "", "", "Argument[1]", "Argument[this]", "taint", "manual"]
88
- ["javax.crypto.spec", "RC2ParameterSpec", True, "RC2ParameterSpec", "", "", "Argument[1]", "Argument[this]", "taint", "manual"]
99
- ["javax.crypto.spec", "RC5ParameterSpec", True, "RC5ParameterSpec", "", "", "Argument[3]", "Argument[this]", "taint", "manual"]
10+
- ["javax.crypto.spec", "HKDFParameterSpec$Builder", True, "addIKM", "(byte[])", "", "Argument[0]", "Argument[this]", "taint", "manual"]
11+
- ["javax.crypto.spec", "HKDFParameterSpec$Builder", True, "addIKM", "(byte[])", "", "Argument[this]", "ReturnValue", "value", "manual"]
12+
- ["javax.crypto.spec", "HKDFParameterSpec$Builder", True, "addIKM", "(SecretKey)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
13+
- ["javax.crypto.spec", "HKDFParameterSpec$Builder", True, "addIKM", "(SecretKey)", "", "Argument[this]", "ReturnValue", "value", "manual"]
14+
- ["javax.crypto.spec", "HKDFParameterSpec$Builder", True, "addSalt", "(byte[])", "", "Argument[0]", "Argument[this]", "taint", "manual"]
15+
- ["javax.crypto.spec", "HKDFParameterSpec$Builder", True, "addSalt", "(byte[])", "", "Argument[this]", "ReturnValue", "value", "manual"]
16+
- ["javax.crypto.spec", "HKDFParameterSpec$Builder", True, "addSalt", "(SecretKey)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
17+
- ["javax.crypto.spec", "HKDFParameterSpec$Builder", True, "addSalt", "(SecretKey)", "", "Argument[this]", "ReturnValue", "value", "manual"]
18+
- ["javax.crypto.spec", "HKDFParameterSpec$Builder", True, "thenExpand", "(byte[],int)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
19+
- ["javax.crypto.spec", "HKDFParameterSpec$Builder", True, "thenExpand", "(byte[],int)", "", "Argument[this]", "ReturnValue", "taint", "manual"]
20+
- ["javax.crypto.spec", "HKDFParameterSpec$Builder", True, "thenExpand", "(byte[],int)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
21+
- ["javax.crypto.spec", "HKDFParameterSpec", False, "expandOnly", "(SecretKey,byte[],int)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
22+
- ["javax.crypto.spec", "HKDFParameterSpec", False, "expandOnly", "(SecretKey,byte[],int)", "", "Argument[1]", "ReturnValue", "taint", "manual"]
23+
- ["javax.crypto.spec", "SecretKeySpec", False, "SecretKeySpec", "(byte[],String)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
24+
- ["javax.crypto.spec", "SecretKeySpec", False, "SecretKeySpec", "(byte[],int,int,String)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
1025
- addsTo:
1126
pack: codeql/java-all
1227
extensible: sinkModel
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import javax.crypto.KDF;
2+
import javax.crypto.spec.HKDFParameterSpec;
3+
4+
public class KDFDataflowTest {
5+
public static String source(String label) {
6+
return "tainted";
7+
}
8+
9+
public static void sink(Object o) {}
10+
11+
public static void main(String[] args) throws Exception {
12+
String userInput = source("");
13+
byte[] taintedBytes = userInput.getBytes();
14+
15+
testBuilderPattern(taintedBytes);
16+
testSeparateBuilder(taintedBytes);
17+
testKDFWithSalt(taintedBytes);
18+
testStaticParameterSpec(taintedBytes);
19+
testCleanUsage();
20+
}
21+
22+
public static void testBuilderPattern(byte[] taintedIKM) throws Exception {
23+
HKDFParameterSpec.Builder builder = HKDFParameterSpec.ofExtract();
24+
builder.addIKM(taintedIKM);
25+
HKDFParameterSpec spec = builder.thenExpand("info".getBytes(), 32);
26+
27+
KDF kdf = KDF.getInstance("HKDF-SHA256");
28+
byte[] result = kdf.deriveData(spec);
29+
sink(result); // $ hasTaintFlow
30+
}
31+
32+
public static void testSeparateBuilder(byte[] taintedIKM) throws Exception {
33+
HKDFParameterSpec.Builder builder1 = HKDFParameterSpec.ofExtract();
34+
HKDFParameterSpec.Builder builder2 = builder1.addIKM(taintedIKM);
35+
HKDFParameterSpec spec = builder2.thenExpand("info".getBytes(), 32);
36+
37+
KDF kdf = KDF.getInstance("HKDF-SHA256");
38+
byte[] result = kdf.deriveData(spec);
39+
sink(result); // $ hasTaintFlow
40+
}
41+
42+
public static void testKDFWithSalt(byte[] taintedIKM) throws Exception {
43+
HKDFParameterSpec.Builder builder = HKDFParameterSpec.ofExtract();
44+
builder.addIKM(taintedIKM);
45+
builder.addSalt("sensitive-salt".getBytes());
46+
HKDFParameterSpec spec = builder.thenExpand("info".getBytes(), 32);
47+
48+
KDF kdf = KDF.getInstance("HKDF-SHA256");
49+
byte[] result = kdf.deriveData(spec);
50+
sink(result); // $ hasTaintFlow
51+
}
52+
53+
public static void testStaticParameterSpec(byte[] taintedIKM) throws Exception {
54+
javax.crypto.spec.SecretKeySpec secretKey = new javax.crypto.spec.SecretKeySpec(taintedIKM, "AES");
55+
HKDFParameterSpec spec = HKDFParameterSpec.expandOnly(
56+
secretKey, "info".getBytes(), 32);
57+
58+
KDF kdf = KDF.getInstance("HKDF-SHA256");
59+
byte[] result = kdf.deriveData(spec);
60+
sink(result); // $ hasTaintFlow
61+
}
62+
63+
public static void testCleanUsage() throws Exception {
64+
byte[] cleanKeyMaterial = "static-key-material".getBytes();
65+
66+
HKDFParameterSpec.Builder builder = HKDFParameterSpec.ofExtract();
67+
builder.addIKM(cleanKeyMaterial);
68+
HKDFParameterSpec spec = builder.thenExpand("info".getBytes(), 32);
69+
70+
KDF kdf = KDF.getInstance("HKDF-SHA256");
71+
byte[] cleanResult = kdf.deriveData(spec);
72+
sink(cleanResult); // Safe - no taint
73+
}
74+
75+
public static void testThenExpand(byte[] cleanIKM) throws Exception {
76+
String userInput = source("");
77+
byte[] taintedInfo = userInput.getBytes();
78+
79+
HKDFParameterSpec.Builder builder = HKDFParameterSpec.ofExtract();
80+
builder.addIKM(cleanIKM);
81+
HKDFParameterSpec spec = builder.thenExpand(taintedInfo, 32);
82+
83+
KDF kdf = KDF.getInstance("HKDF-SHA256");
84+
byte[] result = kdf.deriveData(spec);
85+
sink(result); // $ hasTaintFlow
86+
}
87+
}
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

0 commit comments

Comments
 (0)