Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7de9c05

Browse files
Jami CogswellJami Cogswell
authored andcommitted
use CompileTimeConstantExpr for FN with VarAccess, and remove KeyGeneratorInitConfiguration
1 parent 75794ec commit 7de9c05

3 files changed

Lines changed: 227 additions & 45 deletions

File tree

java/ql/lib/semmle/code/java/security/InsufficientKeySizeQuery.qll

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,19 @@ private int getECKeySize(string algorithm) {
3636
result = algorithm.regexpCapture(".*[a-zA-Z](\\d+)[a-zA-Z].*", 1).toInt()
3737
}
3838

39-
/** Taint configuration tracking flow from a key generator to a `init` method call. */
40-
private class KeyGeneratorInitConfiguration extends TaintTracking::Configuration {
41-
KeyGeneratorInitConfiguration() { this = "KeyGeneratorInitConfiguration" }
42-
43-
override predicate isSource(DataFlow::Node source) {
44-
source.asExpr() instanceof JavaxCryptoKeyGenerator
45-
}
46-
47-
override predicate isSink(DataFlow::Node sink) {
48-
exists(MethodAccess ma |
49-
ma.getMethod() instanceof KeyGeneratorInitMethod and
50-
sink.asExpr() = ma.getQualifier()
51-
)
52-
}
53-
}
54-
39+
// /** Taint configuration tracking flow from a key generator to a `init` method call. */
40+
// private class KeyGeneratorInitConfiguration extends TaintTracking::Configuration {
41+
// KeyGeneratorInitConfiguration() { this = "KeyGeneratorInitConfiguration" }
42+
// override predicate isSource(DataFlow::Node source) {
43+
// source.asExpr() instanceof JavaxCryptoKeyGenerator
44+
// }
45+
// override predicate isSink(DataFlow::Node sink) {
46+
// exists(MethodAccess ma |
47+
// ma.getMethod() instanceof KeyGeneratorInitMethod and
48+
// sink.asExpr() = ma.getQualifier()
49+
// )
50+
// }
51+
// }
5552
/**
5653
* Taint configuration tracking flow from a keypair generator to
5754
* an `initialize` method call.
@@ -80,24 +77,27 @@ private class KeyPairGeneratorInitConfiguration extends TaintTracking::Configura
8077
bindingset[type]
8178
private predicate hasShortSymmetricKey(MethodAccess ma, string msg, string type) {
8279
ma.getMethod() instanceof KeyGeneratorInitMethod and
83-
exists(
84-
JavaxCryptoKeyGenerator jcg, KeyGeneratorInitConfiguration cc, DataFlow::PathNode source,
85-
DataFlow::PathNode dest
86-
|
87-
jcg.getAlgoSpec().(StringLiteral).getValue() = type and
88-
source.getNode().asExpr() = jcg and
89-
dest.getNode().asExpr() = ma.getQualifier() and
90-
//ma.getArgument(0) = var and // ! me
91-
//var.getVariable().getInitializer().getUnderlyingExpr() instanceof IntegerLiteral and // ! me
92-
cc.hasFlowPath(source, dest) //and
93-
//var.getVariable().getInitializer().getUnderlyingExpr().toString().toInt() < 128 // ! me
94-
) and
95-
exists(VarAccess var |
96-
var.getVariable().getInitializer().getUnderlyingExpr() instanceof IntegerLiteral and
97-
var.getVariable().getInitializer().getUnderlyingExpr().toString().toInt() < 128 and
98-
//DataFlow3::localExprFlow(var, ma.getArgument(0)) and
99-
ma.getArgument(0) = var
100-
//ma.getArgument(0).(IntegerLiteral).getIntValue() < 128
80+
// exists(JavaxCryptoKeyGenerator jcg, DataFlow::PathNode source, DataFlow::PathNode dest |
81+
// jcg.getAlgoSpec().(StringLiteral).getValue() = type //and
82+
// //source.getNode().asExpr() = jcg and
83+
// //dest.getNode().asExpr() = ma.getQualifier() //and
84+
// //cc.hasFlowPath(source, dest)
85+
// ) and
86+
(
87+
// exists(VarAccess var |
88+
// var.getVariable().getInitializer().getUnderlyingExpr() instanceof IntegerLiteral and
89+
// var.getVariable().getInitializer().getUnderlyingExpr().toString().toInt() < 128 and
90+
// ma.getArgument(0) = var
91+
// )
92+
// or
93+
// below is better than above?
94+
exists(CompileTimeConstantExpr var |
95+
//var.getUnderlyingExpr() instanceof IntegerLiteral and // can't include this...
96+
var.getIntValue() < 128 and
97+
ma.getArgument(0) = var
98+
)
99+
or
100+
ma.getArgument(0).(IntegerLiteral).getIntValue() < 128
101101
) and
102102
msg = "Key size should be at least 128 bits for " + type + " encryption."
103103
}
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
import semmle.code.java.security.Encryption
2+
import semmle.code.java.dataflow.TaintTracking
3+
import semmle.code.java.dataflow.DataFlow3
4+
5+
/** The Java class `java.security.spec.ECGenParameterSpec`. */
6+
private class ECGenParameterSpec extends RefType {
7+
ECGenParameterSpec() { this.hasQualifiedName("java.security.spec", "ECGenParameterSpec") }
8+
}
9+
10+
/** The `init` method declared in `javax.crypto.KeyGenerator`. */
11+
private class KeyGeneratorInitMethod extends Method {
12+
KeyGeneratorInitMethod() {
13+
this.getDeclaringType() instanceof KeyGenerator and
14+
this.hasName("init")
15+
}
16+
}
17+
18+
/** The `initialize` method declared in `java.security.KeyPairGenerator`. */
19+
private class KeyPairGeneratorInitMethod extends Method {
20+
KeyPairGeneratorInitMethod() {
21+
this.getDeclaringType() instanceof KeyPairGenerator and
22+
this.hasName("initialize")
23+
}
24+
}
25+
26+
/** Returns the key size in the EC algorithm string */
27+
bindingset[algorithm]
28+
private int getECKeySize(string algorithm) {
29+
algorithm.matches("sec%") and // specification such as "secp256r1"
30+
result = algorithm.regexpCapture("sec[p|t](\\d+)[a-zA-Z].*", 1).toInt()
31+
or
32+
algorithm.matches("X9.62%") and //specification such as "X9.62 prime192v2"
33+
result = algorithm.regexpCapture("X9\\.62 .*[a-zA-Z](\\d+)[a-zA-Z].*", 1).toInt()
34+
or
35+
(algorithm.matches("prime%") or algorithm.matches("c2tnb%")) and //specification such as "prime192v2"
36+
result = algorithm.regexpCapture(".*[a-zA-Z](\\d+)[a-zA-Z].*", 1).toInt()
37+
}
38+
39+
/** Taint configuration tracking flow from a key generator to a `init` method call. */
40+
private class KeyGeneratorInitConfiguration extends TaintTracking::Configuration {
41+
KeyGeneratorInitConfiguration() { this = "KeyGeneratorInitConfiguration" }
42+
43+
override predicate isSource(DataFlow::Node source) {
44+
source.asExpr() instanceof JavaxCryptoKeyGenerator
45+
}
46+
47+
override predicate isSink(DataFlow::Node sink) {
48+
exists(MethodAccess ma |
49+
ma.getMethod() instanceof KeyGeneratorInitMethod and
50+
sink.asExpr() = ma.getQualifier()
51+
)
52+
}
53+
}
54+
55+
/**
56+
* Taint configuration tracking flow from a keypair generator to
57+
* an `initialize` method call.
58+
*/
59+
private class KeyPairGeneratorInitConfiguration extends TaintTracking::Configuration {
60+
KeyPairGeneratorInitConfiguration() { this = "KeyPairGeneratorInitConfiguration" }
61+
62+
override predicate isSource(DataFlow::Node source) {
63+
source.asExpr() instanceof JavaSecurityKeyPairGenerator
64+
}
65+
66+
override predicate isSink(DataFlow::Node sink) {
67+
exists(MethodAccess ma |
68+
ma.getMethod() instanceof KeyPairGeneratorInitMethod and
69+
sink.asExpr() = ma.getQualifier()
70+
)
71+
}
72+
}
73+
74+
/**
75+
* Holds if a symmetric `KeyGenerator` implementing encryption algorithm
76+
* `type` and initialized by `ma` uses an insufficient key size.
77+
*
78+
* `msg` provides a human-readable description of the problem.
79+
*/
80+
bindingset[type]
81+
private predicate hasShortSymmetricKey(MethodAccess ma, string msg, string type) {
82+
ma.getMethod() instanceof KeyGeneratorInitMethod and
83+
exists(
84+
JavaxCryptoKeyGenerator jcg, KeyGeneratorInitConfiguration cc, DataFlow::PathNode source,
85+
DataFlow::PathNode dest
86+
|
87+
jcg.getAlgoSpec().(StringLiteral).getValue() = type and
88+
source.getNode().asExpr() = jcg and
89+
dest.getNode().asExpr() = ma.getQualifier() and
90+
//ma.getArgument(0) = var and // ! me
91+
//var.getVariable().getInitializer().getUnderlyingExpr() instanceof IntegerLiteral and // ! me
92+
cc.hasFlowPath(source, dest) //and
93+
//var.getVariable().getInitializer().getUnderlyingExpr().toString().toInt() < 128 // ! me
94+
) and
95+
exists(VarAccess var |
96+
var.getVariable().getInitializer().getUnderlyingExpr() instanceof IntegerLiteral and
97+
var.getVariable().getInitializer().getUnderlyingExpr().toString().toInt() < 128 and
98+
//DataFlow3::localExprFlow(var, ma.getArgument(0)) and
99+
ma.getArgument(0) = var
100+
//ma.getArgument(0).(IntegerLiteral).getIntValue() < 128
101+
) and
102+
msg = "Key size should be at least 128 bits for " + type + " encryption."
103+
}
104+
105+
/**
106+
* Holds if an AES `KeyGenerator` initialized by `ma` uses an insufficient key size.
107+
* `msg` provides a human-readable description of the problem.
108+
*/
109+
private predicate hasShortAESKey(MethodAccess ma, string msg) {
110+
hasShortSymmetricKey(ma, msg, "AES")
111+
}
112+
113+
/**
114+
* Holds if an asymmetric `KeyPairGenerator` implementing encryption algorithm
115+
* `type` and initialized by `ma` uses an insufficient key size.
116+
*
117+
* `msg` provides a human-readable description of the problem.
118+
*/
119+
bindingset[type]
120+
private predicate hasShortAsymmetricKeyPair(MethodAccess ma, string msg, string type) {
121+
ma.getMethod() instanceof KeyPairGeneratorInitMethod and
122+
exists(
123+
JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorInitConfiguration kc,
124+
DataFlow::PathNode source, DataFlow::PathNode dest
125+
|
126+
jpg.getAlgoSpec().(StringLiteral).getValue().toUpperCase() = type and
127+
source.getNode().asExpr() = jpg and
128+
dest.getNode().asExpr() = ma.getQualifier() and
129+
kc.hasFlowPath(source, dest)
130+
) and
131+
ma.getArgument(0).(IntegerLiteral).getIntValue() < 2048 and
132+
msg = "Key size should be at least 2048 bits for " + type + " encryption."
133+
}
134+
135+
/**
136+
* Holds if a DSA `KeyPairGenerator` initialized by `ma` uses an insufficient key size.
137+
*
138+
* `msg` provides a human-readable description of the problem.
139+
*/
140+
private predicate hasShortDsaKeyPair(MethodAccess ma, string msg) {
141+
hasShortAsymmetricKeyPair(ma, msg, "DSA") or
142+
hasShortAsymmetricKeyPair(ma, msg, "DH")
143+
}
144+
145+
/**
146+
* Holds if a RSA `KeyPairGenerator` initialized by `ma` uses an insufficient key size.
147+
*
148+
* `msg` provides a human-readable description of the problem.
149+
*/
150+
private predicate hasShortRsaKeyPair(MethodAccess ma, string msg) {
151+
hasShortAsymmetricKeyPair(ma, msg, "RSA")
152+
}
153+
154+
/**
155+
* Holds if an EC `KeyPairGenerator` initialized by `ma` uses an insufficient key size.
156+
*
157+
* `msg` provides a human-readable description of the problem.
158+
*/
159+
private predicate hasShortECKeyPair(MethodAccess ma, string msg) {
160+
ma.getMethod() instanceof KeyPairGeneratorInitMethod and
161+
exists(
162+
JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorInitConfiguration kc,
163+
DataFlow::PathNode source, DataFlow::PathNode dest, ClassInstanceExpr cie
164+
|
165+
jpg.getAlgoSpec().(StringLiteral).getValue().matches("EC%") and // ECC variants such as ECDH and ECDSA
166+
source.getNode().asExpr() = jpg and
167+
dest.getNode().asExpr() = ma.getQualifier() and
168+
kc.hasFlowPath(source, dest) and
169+
DataFlow::localExprFlow(cie, ma.getArgument(0)) and
170+
ma.getArgument(0).getType() instanceof ECGenParameterSpec and
171+
getECKeySize(cie.getArgument(0).(StringLiteral).getValue()) < 256
172+
) and
173+
msg = "Key size should be at least 256 bits for EC encryption."
174+
}
175+
176+
// ! refactor this so can use 'path-problem' select clause instead?
177+
predicate hasInsufficientKeySize(Expr e, string msg) {
178+
hasShortAESKey(e, msg) or
179+
hasShortDsaKeyPair(e, msg) or
180+
hasShortRsaKeyPair(e, msg) or
181+
hasShortECKeyPair(e, msg)
182+
}

java/ql/test/query-tests/security/CWE-326/InsufficientKeySizeTest.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,18 +97,18 @@ public void cryptoMethod() throws java.security.NoSuchAlgorithmException, java.s
9797
// BAD: Key size is less than 128
9898
keyGen3.init(size1); // $ hasInsufficientKeySize
9999

100-
int size2 = 1024;
101-
KeyPairGenerator keyPairGen18 = KeyPairGenerator.getInstance("RSA");
102-
// BAD: Key size is less than 2048
103-
keyPairGen18.initialize(size2); // $ hasInsufficientKeySize
100+
// int size2 = 1024;
101+
// KeyPairGenerator keyPairGen18 = KeyPairGenerator.getInstance("RSA");
102+
// // BAD: Key size is less than 2048
103+
// keyPairGen18.initialize(size2); // $ hasInsufficientKeySize
104104

105-
int keysize = 64;
106-
test(keysize);
105+
// int keysize = 64;
106+
// test(keysize);
107107
}
108108

109-
public void test(int keySize) throws java.security.NoSuchAlgorithmException, java.security.InvalidAlgorithmParameterException {
110-
KeyGenerator keyGen4 = KeyGenerator.getInstance("AES");
111-
// BAD: Key size is less than 128
112-
keyGen4.init(keySize); // $ hasInsufficientKeySize
113-
}
109+
// public void test(int keySize) throws java.security.NoSuchAlgorithmException, java.security.InvalidAlgorithmParameterException {
110+
// KeyGenerator keyGen4 = KeyGenerator.getInstance("AES");
111+
// // BAD: Key size is less than 128
112+
// keyGen4.init(keySize); // $ hasInsufficientKeySize
113+
// }
114114
}

0 commit comments

Comments
 (0)