@@ -2,7 +2,7 @@ import semmle.code.java.security.Encryption
22import semmle.code.java.dataflow.TaintTracking
33import semmle.code.java.dataflow.DataFlow
44
5- //import DataFlow::PathGraph
5+ // ******* DATAFLOW *******************************************************************************
66/**
77 * Asymmetric (RSA, DSA, DH) key length data flow tracking configuration.
88 */
@@ -14,6 +14,8 @@ class AsymmetricKeyTrackingConfiguration extends DataFlow::Configuration {
1414 integer .getIntValue ( ) < 2048 and
1515 source .asExpr ( ) = integer
1616 or
17+ // The below only handles cases when variables are used (both locally in a method and between methods)
18+ // The above adds handling for direct use of integers as well
1719 var .getVariable ( ) .getInitializer ( ) .getUnderlyingExpr ( ) instanceof IntegerLiteral and
1820 var .getVariable ( ) .getInitializer ( ) .getUnderlyingExpr ( ) .toString ( ) .toInt ( ) < 2048 and
1921 source .asExpr ( ) = var .getVariable ( ) .getInitializer ( )
@@ -28,11 +30,101 @@ class AsymmetricKeyTrackingConfiguration extends DataFlow::Configuration {
2830 }
2931}
3032
33+ /**
34+ * Symmetric (AES) key length data flow tracking configuration.
35+ */
36+ class SymmetricKeyTrackingConfiguration extends DataFlow:: Configuration {
37+ SymmetricKeyTrackingConfiguration ( ) { this = "SymmetricKeyTrackingConfiguration" }
38+
39+ override predicate isSource ( DataFlow:: Node source ) {
40+ exists ( IntegerLiteral integer , VarAccess var |
41+ integer .getIntValue ( ) < 128 and
42+ source .asExpr ( ) = integer
43+ or
44+ // The below only handles cases when variables are used (both locally in a method and between methods)
45+ // The above adds handling for direct use of integers as well
46+ var .getVariable ( ) .getInitializer ( ) .getUnderlyingExpr ( ) instanceof IntegerLiteral and
47+ var .getVariable ( ) .getInitializer ( ) .getUnderlyingExpr ( ) .toString ( ) .toInt ( ) < 128 and
48+ source .asExpr ( ) = var .getVariable ( ) .getInitializer ( )
49+ )
50+ }
51+
52+ override predicate isSink ( DataFlow:: Node sink ) {
53+ exists ( MethodAccess ma |
54+ ma .getMethod ( ) instanceof KeyGeneratorInitMethod and
55+ sink .asExpr ( ) = ma .getArgument ( 0 )
56+ )
57+ }
58+ }
59+
60+ /**
61+ * Symmetric (AES) key length data flow tracking configuration.
62+ */
63+ class SymmetricKeyTrackingConfiguration2 extends DataFlow:: Configuration {
64+ SymmetricKeyTrackingConfiguration2 ( ) { this = "SymmetricKeyTrackingConfiguration2" }
65+
66+ override predicate isSource ( DataFlow:: Node source ) {
67+ source .asExpr ( ) instanceof IntegerLiteral and
68+ source .toString ( ) .toInt ( ) < 128
69+ }
70+
71+ override predicate isSink ( DataFlow:: Node sink ) {
72+ exists ( MethodAccess ma |
73+ ma .getMethod ( ) instanceof KeyGeneratorInitMethod and
74+ sink .asExpr ( ) = ma .getArgument ( 0 )
75+ )
76+ }
77+ }
78+
79+ class UnsafeSymmetricKeySize extends IntegerLiteral {
80+ UnsafeSymmetricKeySize ( ) { this .getIntValue ( ) < 128 }
81+ }
82+
83+ class UnsafeAsymmetricKeySize extends IntegerLiteral {
84+ UnsafeAsymmetricKeySize ( ) { this .getIntValue ( ) < 2048 }
85+ }
86+
87+ class UnsafeKeySize extends IntegerLiteral {
88+ UnsafeKeySize ( ) {
89+ this instanceof UnsafeAsymmetricKeySize and
90+ exists ( MethodAccess ma | ma .getMethod ( ) instanceof KeyPairGeneratorInitMethod )
91+ or
92+ this instanceof UnsafeSymmetricKeySize and
93+ exists ( MethodAccess ma | ma .getMethod ( ) instanceof KeyGeneratorInitMethod )
94+ }
95+ }
96+
97+ class KeyInitMethod extends Method {
98+ KeyInitMethod ( ) {
99+ this instanceof KeyGeneratorInitMethod or
100+ this instanceof KeyPairGeneratorInitMethod
101+ }
102+ }
103+
104+ /**
105+ * key length data flow tracking configuration.
106+ */
107+ class KeyTrackingConfiguration extends DataFlow:: Configuration {
108+ KeyTrackingConfiguration ( ) { this = "KeyTrackingConfiguration" }
109+
110+ override predicate isSource ( DataFlow:: Node source ) { source .asExpr ( ) instanceof UnsafeKeySize }
111+
112+ override predicate isSink ( DataFlow:: Node sink ) {
113+ exists ( MethodAccess ma |
114+ ma .getMethod ( ) instanceof KeyInitMethod and
115+ sink .asExpr ( ) = ma .getArgument ( 0 )
116+ )
117+ }
118+ }
119+
120+ // ******* DATAFLOW *******************************************************************************
121+ // ! move to Encryption.qll?
31122/** The Java class `java.security.spec.ECGenParameterSpec`. */
32123private class ECGenParameterSpec extends RefType {
33124 ECGenParameterSpec ( ) { this .hasQualifiedName ( "java.security.spec" , "ECGenParameterSpec" ) }
34125}
35126
127+ // ! move to Encryption.qll?
36128/** The `init` method declared in `javax.crypto.KeyGenerator`. */
37129private class KeyGeneratorInitMethod extends Method {
38130 KeyGeneratorInitMethod ( ) {
@@ -41,6 +133,7 @@ private class KeyGeneratorInitMethod extends Method {
41133 }
42134}
43135
136+ // ! move to Encryption.qll?
44137/** The `initialize` method declared in `java.security.KeyPairGenerator`. */
45138private class KeyPairGeneratorInitMethod extends Method {
46139 KeyPairGeneratorInitMethod ( ) {
@@ -97,6 +190,46 @@ private class KeyPairGeneratorInitConfiguration extends TaintTracking::Configura
97190 }
98191}
99192
193+ /**
194+ * Holds if a symmetric `KeyGenerator` implementing encryption algorithm
195+ * `type` and initialized by `ma` uses an insufficient key size.
196+ *
197+ * `msg` provides a human-readable description of the problem.
198+ */
199+ //bindingset[type]
200+ private predicate hasShortSymmetricKey_TEST ( ) {
201+ exists (
202+ SymmetricKeyTrackingConfiguration2 cfg , DataFlow:: PathNode source , DataFlow:: PathNode sink
203+ |
204+ cfg .hasFlowPath ( source , sink )
205+ )
206+ // ma.getMethod() instanceof KeyGeneratorInitMethod and
207+ // // flow needed to correctly determine algorithm type and
208+ // // not match to ANY symmetric algorithm (although doesn't really matter since only have AES currently...)
209+ // exists(
210+ // JavaxCryptoKeyGenerator jcg, KeyGeneratorInitConfiguration cc, DataFlow::PathNode source,
211+ // DataFlow::PathNode dest
212+ // |
213+ // jcg.getAlgoSpec().(StringLiteral).getValue() = type and
214+ // source.getNode().asExpr() = jcg and
215+ // dest.getNode().asExpr() = ma.getQualifier() and
216+ // cc.hasFlowPath(source, dest)
217+ // ) and
218+ // (
219+ // // VarAccess case needed to handle FN of key-size stored in a variable
220+ // // Note: cannot use CompileTimeConstantExpr since will miss cases when variable is not a compile-time constant
221+ // // (e.g. not declared `final` in Java)
222+ // exists(VarAccess var |
223+ // var.getVariable().getInitializer().getUnderlyingExpr() instanceof IntegerLiteral and
224+ // var.getVariable().getInitializer().getUnderlyingExpr().toString().toInt() < 128 and
225+ // ma.getArgument(0) = var
226+ // )
227+ // or
228+ // ma.getArgument(0).(IntegerLiteral).getIntValue() < 128
229+ // ) and
230+ // msg = "Key size should be at least 128 bits for " + type + " encryption."
231+ }
232+
100233/**
101234 * Holds if a symmetric `KeyGenerator` implementing encryption algorithm
102235 * `type` and initialized by `ma` uses an insufficient key size.
@@ -262,3 +395,9 @@ predicate hasInsufficientKeySize(Expr e, string msg) {
262395 hasShortRsaKeyPair ( e , msg ) or
263396 hasShortECKeyPair ( e , msg )
264397}
398+
399+ predicate hasInsufficientKeySize2 ( DataFlow:: PathNode source , DataFlow:: PathNode sink ) {
400+ exists ( AsymmetricKeyTrackingConfiguration config1 | config1 .hasFlowPath ( source , sink ) )
401+ or
402+ exists ( SymmetricKeyTrackingConfiguration2 config2 | config2 .hasFlowPath ( source , sink ) )
403+ }
0 commit comments